diff --git a/CHANGELOG.md b/CHANGELOG.md
index cdc56102..08d846e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,20 @@
+# 0.7.1
+
+### Minor API changes
+
+- group indices can no longer be accessed via `.groups`. They are now listed as columns in `.nodes` (#587, @michaeldeistler). Update your code as follows:
+```python
+# Before:
+exc_group_inds = cell.groups["exc"]
+# Now:
+exc_group_inds = cell.exc.nodes.index.to_numpy()
+```
+
+### Bug fixes
+
+- Fix bug for `groups` when `.set_ncomp` was run (#587, @michaeldeistler)
+
+
# 0.7.0
### New Features
diff --git a/docs/tutorials/06_groups.ipynb b/docs/tutorials/06_groups.ipynb
index 73a0c713..0fbe8e3c 100644
--- a/docs/tutorials/06_groups.ipynb
+++ b/docs/tutorials/06_groups.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "51419bb0",
+ "id": "45049a58",
"metadata": {},
"source": [
"# Defining groups\n",
@@ -41,7 +41,7 @@
{
"cell_type": "code",
"execution_count": 1,
- "id": "d703515b",
+ "id": "f30222dd",
"metadata": {},
"outputs": [],
"source": [
@@ -64,7 +64,7 @@
},
{
"cell_type": "markdown",
- "id": "94f247bc",
+ "id": "cfb5a7a1",
"metadata": {},
"source": [
"First, we define a network as you saw in the [previous tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/02_small_network.html):"
@@ -73,7 +73,7 @@
{
"cell_type": "code",
"execution_count": 2,
- "id": "10c4f776",
+ "id": "48d0c79b",
"metadata": {},
"outputs": [],
"source": [
@@ -93,7 +93,7 @@
},
{
"cell_type": "markdown",
- "id": "465fc6fa",
+ "id": "943d80dc",
"metadata": {},
"source": [
"### Group: apical dendrites\n",
@@ -103,7 +103,7 @@
{
"cell_type": "code",
"execution_count": 3,
- "id": "3f23fceb",
+ "id": "f1e6a29f",
"metadata": {},
"outputs": [],
"source": [
@@ -114,7 +114,7 @@
},
{
"cell_type": "markdown",
- "id": "ee58e3e9",
+ "id": "cadc2571",
"metadata": {},
"source": [
"After this, we can access `network.apical` as we previously accesses anything else:"
@@ -123,7 +123,7 @@
{
"cell_type": "code",
"execution_count": 4,
- "id": "5b2c9ee1",
+ "id": "6620dfad",
"metadata": {},
"outputs": [],
"source": [
@@ -133,13 +133,405 @@
{
"cell_type": "code",
"execution_count": 5,
- "id": "1e6efa3e",
+ "id": "c5b86bd9",
"metadata": {},
"outputs": [
{
"data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " local_cell_index | \n",
+ " local_branch_index | \n",
+ " local_comp_index | \n",
+ " length | \n",
+ " radius | \n",
+ " axial_resistivity | \n",
+ " capacitance | \n",
+ " v | \n",
+ " Na | \n",
+ " Na_gNa | \n",
+ " ... | \n",
+ " eK | \n",
+ " K_n | \n",
+ " Leak | \n",
+ " Leak_gLeak | \n",
+ " Leak_eLeak | \n",
+ " apical | \n",
+ " global_cell_index | \n",
+ " global_branch_index | \n",
+ " global_comp_index | \n",
+ " controlled_by_param | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 3 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " 6 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " 7 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 10 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 1 | \n",
+ " 5 | \n",
+ " 10 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 11 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 1 | \n",
+ " 5 | \n",
+ " 11 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 1 | \n",
+ " 7 | \n",
+ " 14 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 1 | \n",
+ " 7 | \n",
+ " 15 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 18 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 2 | \n",
+ " 9 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 19 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 2 | \n",
+ " 9 | \n",
+ " 19 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 22 | \n",
+ " 2 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 2 | \n",
+ " 11 | \n",
+ " 22 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 23 | \n",
+ " 2 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.05 | \n",
+ " ... | \n",
+ " -90.0 | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 2 | \n",
+ " 11 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
12 rows × 26 columns
\n",
+ "
"
+ ],
"text/plain": [
- "View with 3 different channels. Use `.nodes` for details."
+ " local_cell_index local_branch_index local_comp_index length radius \\\n",
+ "2 0 0 0 10.0 0.3 \n",
+ "3 0 0 1 10.0 0.3 \n",
+ "6 0 1 0 10.0 0.3 \n",
+ "7 0 1 1 10.0 0.3 \n",
+ "10 1 0 0 10.0 0.3 \n",
+ "11 1 0 1 10.0 0.3 \n",
+ "14 1 1 0 10.0 0.3 \n",
+ "15 1 1 1 10.0 0.3 \n",
+ "18 2 0 0 10.0 0.3 \n",
+ "19 2 0 1 10.0 0.3 \n",
+ "22 2 1 0 10.0 0.3 \n",
+ "23 2 1 1 10.0 0.3 \n",
+ "\n",
+ " axial_resistivity capacitance v Na Na_gNa ... eK K_n Leak \\\n",
+ "2 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "3 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "6 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "7 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "10 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "11 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "14 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "15 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "18 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "19 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "22 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "23 5000.0 1.0 -70.0 True 0.05 ... -90.0 0.2 True \n",
+ "\n",
+ " Leak_gLeak Leak_eLeak apical global_cell_index global_branch_index \\\n",
+ "2 0.0001 -70.0 True 0 1 \n",
+ "3 0.0001 -70.0 True 0 1 \n",
+ "6 0.0001 -70.0 True 0 3 \n",
+ "7 0.0001 -70.0 True 0 3 \n",
+ "10 0.0001 -70.0 True 1 5 \n",
+ "11 0.0001 -70.0 True 1 5 \n",
+ "14 0.0001 -70.0 True 1 7 \n",
+ "15 0.0001 -70.0 True 1 7 \n",
+ "18 0.0001 -70.0 True 2 9 \n",
+ "19 0.0001 -70.0 True 2 9 \n",
+ "22 0.0001 -70.0 True 2 11 \n",
+ "23 0.0001 -70.0 True 2 11 \n",
+ "\n",
+ " global_comp_index controlled_by_param \n",
+ "2 2 0 \n",
+ "3 3 0 \n",
+ "6 6 0 \n",
+ "7 7 0 \n",
+ "10 10 0 \n",
+ "11 11 0 \n",
+ "14 14 0 \n",
+ "15 15 0 \n",
+ "18 18 0 \n",
+ "19 19 0 \n",
+ "22 22 0 \n",
+ "23 23 0 \n",
+ "\n",
+ "[12 rows x 26 columns]"
]
},
"execution_count": 5,
@@ -148,12 +540,12 @@
}
],
"source": [
- "network.apical.view"
+ "network.apical.nodes"
]
},
{
"cell_type": "markdown",
- "id": "ac885848",
+ "id": "58af9da8",
"metadata": {},
"source": [
"### Group: fast spiking\n",
@@ -163,7 +555,7 @@
{
"cell_type": "code",
"execution_count": 6,
- "id": "0b8e9b38",
+ "id": "73574946",
"metadata": {},
"outputs": [],
"source": [
@@ -174,7 +566,7 @@
{
"cell_type": "code",
"execution_count": 7,
- "id": "25322ebf",
+ "id": "309244bb",
"metadata": {},
"outputs": [],
"source": [
@@ -184,13 +576,517 @@
{
"cell_type": "code",
"execution_count": 8,
- "id": "f98f4e74",
+ "id": "fbd2ef7a",
"metadata": {},
"outputs": [
{
"data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " local_cell_index | \n",
+ " local_branch_index | \n",
+ " local_comp_index | \n",
+ " length | \n",
+ " radius | \n",
+ " axial_resistivity | \n",
+ " capacitance | \n",
+ " v | \n",
+ " Na | \n",
+ " Na_gNa | \n",
+ " ... | \n",
+ " K_n | \n",
+ " Leak | \n",
+ " Leak_gLeak | \n",
+ " Leak_eLeak | \n",
+ " apical | \n",
+ " fast_spiking | \n",
+ " global_cell_index | \n",
+ " global_branch_index | \n",
+ " global_comp_index | \n",
+ " controlled_by_param | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 1.0 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " False | \n",
+ " True | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 1.0 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " False | \n",
+ " True | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " True | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " True | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 3 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 1.0 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " False | \n",
+ " True | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " 4 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 1.0 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " False | \n",
+ " True | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " 5 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " True | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " 6 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " True | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " 7 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 8 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 1.0 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " False | \n",
+ " True | \n",
+ " 1 | \n",
+ " 4 | \n",
+ " 8 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 1.0 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " False | \n",
+ " True | \n",
+ " 1 | \n",
+ " 4 | \n",
+ " 9 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 10 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " True | \n",
+ " 1 | \n",
+ " 5 | \n",
+ " 10 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 11 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " True | \n",
+ " 1 | \n",
+ " 5 | \n",
+ " 11 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 12 | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 1.0 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " False | \n",
+ " True | \n",
+ " 1 | \n",
+ " 6 | \n",
+ " 12 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 13 | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 1.0 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " False | \n",
+ " True | \n",
+ " 1 | \n",
+ " 6 | \n",
+ " 13 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 1 | \n",
+ " 3 | \n",
+ " 0 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " True | \n",
+ " 1 | \n",
+ " 7 | \n",
+ " 14 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 1 | \n",
+ " 3 | \n",
+ " 1 | \n",
+ " 10.0 | \n",
+ " 0.3 | \n",
+ " 5000.0 | \n",
+ " 1.0 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " 0.4 | \n",
+ " ... | \n",
+ " 0.2 | \n",
+ " True | \n",
+ " 0.0001 | \n",
+ " -70.0 | \n",
+ " True | \n",
+ " True | \n",
+ " 1 | \n",
+ " 7 | \n",
+ " 15 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
16 rows × 27 columns
\n",
+ "
"
+ ],
"text/plain": [
- "View with 3 different channels. Use `.nodes` for details."
+ " local_cell_index local_branch_index local_comp_index length radius \\\n",
+ "0 0 0 0 10.0 1.0 \n",
+ "1 0 0 1 10.0 1.0 \n",
+ "2 0 1 0 10.0 0.3 \n",
+ "3 0 1 1 10.0 0.3 \n",
+ "4 0 2 0 10.0 1.0 \n",
+ "5 0 2 1 10.0 1.0 \n",
+ "6 0 3 0 10.0 0.3 \n",
+ "7 0 3 1 10.0 0.3 \n",
+ "8 1 0 0 10.0 1.0 \n",
+ "9 1 0 1 10.0 1.0 \n",
+ "10 1 1 0 10.0 0.3 \n",
+ "11 1 1 1 10.0 0.3 \n",
+ "12 1 2 0 10.0 1.0 \n",
+ "13 1 2 1 10.0 1.0 \n",
+ "14 1 3 0 10.0 0.3 \n",
+ "15 1 3 1 10.0 0.3 \n",
+ "\n",
+ " axial_resistivity capacitance v Na Na_gNa ... K_n Leak \\\n",
+ "0 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "1 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "2 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "3 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "4 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "5 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "6 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "7 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "8 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "9 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "10 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "11 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "12 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "13 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "14 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "15 5000.0 1.0 -70.0 True 0.4 ... 0.2 True \n",
+ "\n",
+ " Leak_gLeak Leak_eLeak apical fast_spiking global_cell_index \\\n",
+ "0 0.0001 -70.0 False True 0 \n",
+ "1 0.0001 -70.0 False True 0 \n",
+ "2 0.0001 -70.0 True True 0 \n",
+ "3 0.0001 -70.0 True True 0 \n",
+ "4 0.0001 -70.0 False True 0 \n",
+ "5 0.0001 -70.0 False True 0 \n",
+ "6 0.0001 -70.0 True True 0 \n",
+ "7 0.0001 -70.0 True True 0 \n",
+ "8 0.0001 -70.0 False True 1 \n",
+ "9 0.0001 -70.0 False True 1 \n",
+ "10 0.0001 -70.0 True True 1 \n",
+ "11 0.0001 -70.0 True True 1 \n",
+ "12 0.0001 -70.0 False True 1 \n",
+ "13 0.0001 -70.0 False True 1 \n",
+ "14 0.0001 -70.0 True True 1 \n",
+ "15 0.0001 -70.0 True True 1 \n",
+ "\n",
+ " global_branch_index global_comp_index controlled_by_param \n",
+ "0 0 0 0 \n",
+ "1 0 1 0 \n",
+ "2 1 2 0 \n",
+ "3 1 3 0 \n",
+ "4 2 4 0 \n",
+ "5 2 5 0 \n",
+ "6 3 6 0 \n",
+ "7 3 7 0 \n",
+ "8 4 8 0 \n",
+ "9 4 9 0 \n",
+ "10 5 10 0 \n",
+ "11 5 11 0 \n",
+ "12 6 12 0 \n",
+ "13 6 13 0 \n",
+ "14 7 14 0 \n",
+ "15 7 15 0 \n",
+ "\n",
+ "[16 rows x 27 columns]"
]
},
"execution_count": 8,
@@ -199,12 +1095,12 @@
}
],
"source": [
- "network.fast_spiking.view"
+ "network.fast_spiking.nodes"
]
},
{
"cell_type": "markdown",
- "id": "c8ad35a5",
+ "id": "af5556df",
"metadata": {},
"source": [
"### Groups from SWC files"
@@ -212,19 +1108,19 @@
},
{
"cell_type": "markdown",
- "id": "72de2fb6",
+ "id": "ca83dfe3",
"metadata": {},
"source": [
"If you are reading `.swc` morphologigies, you can automatically assign groups with \n",
"```python\n",
- "jx.read_swc(file_name, ncomp=n, assign_groups=True).\n",
+ "jx.read_swc(file_name, ncomp=n, assign_groups=True) # assign_groups=True is the default\n",
"```\n",
"After that, you can directly use `cell.soma`, `cell.apical`, `cell.basal`, or `cell.axon`."
]
},
{
"cell_type": "markdown",
- "id": "e08a5b66",
+ "id": "135f21c1",
"metadata": {},
"source": [
"### How groups are interpreted by `.make_trainable()`\n",
@@ -234,7 +1130,7 @@
{
"cell_type": "code",
"execution_count": 9,
- "id": "a5d4f8ca",
+ "id": "c860018e",
"metadata": {},
"outputs": [
{
@@ -251,7 +1147,7 @@
},
{
"cell_type": "markdown",
- "id": "99082cca",
+ "id": "d7692233",
"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:"
@@ -260,7 +1156,7 @@
{
"cell_type": "code",
"execution_count": 10,
- "id": "62b0dc0c",
+ "id": "6e272a11",
"metadata": {},
"outputs": [
{
@@ -280,7 +1176,7 @@
},
{
"cell_type": "markdown",
- "id": "4941d565",
+ "id": "a991301a",
"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]):"
@@ -289,7 +1185,7 @@
{
"cell_type": "code",
"execution_count": 11,
- "id": "4e6108e9",
+ "id": "87dcd69f",
"metadata": {},
"outputs": [
{
@@ -307,7 +1203,7 @@
{
"cell_type": "code",
"execution_count": 12,
- "id": "13db06ab",
+ "id": "12ebb94d",
"metadata": {},
"outputs": [
{
@@ -328,7 +1224,7 @@
},
{
"cell_type": "markdown",
- "id": "3d6a4dee",
+ "id": "777e2a3c",
"metadata": {},
"source": [
"This generated two parameters for the axial resistivitiy, each corresponding to one cell."
@@ -336,7 +1232,7 @@
},
{
"cell_type": "markdown",
- "id": "3ed0a8d6",
+ "id": "d4373f62",
"metadata": {},
"source": [
"### Summary"
@@ -344,7 +1240,7 @@
},
{
"cell_type": "markdown",
- "id": "4476ff6b",
+ "id": "d3ba38ba",
"metadata": {},
"source": [
"Groups allow you to organize your simulation in a more intuitive way, and they allow to perform parameter sharing with `make_trainable()`."
diff --git a/docs/tutorials/09_advanced_indexing.ipynb b/docs/tutorials/09_advanced_indexing.ipynb
index 12328c00..12bccc0b 100644
--- a/docs/tutorials/09_advanced_indexing.ipynb
+++ b/docs/tutorials/09_advanced_indexing.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "1710a74b",
+ "id": "c891f0aa",
"metadata": {},
"source": [
"# Customizing synaptic parameters"
@@ -10,7 +10,7 @@
},
{
"cell_type": "markdown",
- "id": "1597ec00",
+ "id": "28381f12",
"metadata": {},
"source": [
"In this tutorial, you will learn how to:\n",
@@ -43,7 +43,7 @@
},
{
"cell_type": "markdown",
- "id": "fd9a49de",
+ "id": "c5b8664a",
"metadata": {},
"source": [
"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",
@@ -54,7 +54,7 @@
{
"cell_type": "code",
"execution_count": 1,
- "id": "78266a05",
+ "id": "303bcce1",
"metadata": {
"tags": []
},
@@ -68,7 +68,7 @@
},
{
"cell_type": "markdown",
- "id": "22d63dcf",
+ "id": "32e9a2d9",
"metadata": {},
"source": [
"### Preface: Building the network\n",
@@ -79,7 +79,7 @@
{
"cell_type": "code",
"execution_count": 2,
- "id": "4603896e",
+ "id": "fdf3cf23",
"metadata": {
"tags": []
},
@@ -97,7 +97,7 @@
},
{
"cell_type": "markdown",
- "id": "396be7bd",
+ "id": "ad4adfbd",
"metadata": {},
"source": [
"### Setting individual synapse parameters\n",
@@ -108,7 +108,7 @@
{
"cell_type": "code",
"execution_count": 3,
- "id": "15604d2e",
+ "id": "67a0f672",
"metadata": {
"tags": []
},
@@ -153,11 +153,11 @@
" 0 | \n",
" 0 | \n",
" 0 | \n",
- " 13 | \n",
+ " 12 | \n",
" IonotropicSynapse | \n",
" 0 | \n",
" 0.25 | \n",
- " 0.75 | \n",
+ " 0.25 | \n",
" 0.0001 | \n",
" 0.0 | \n",
" 0.025 | \n",
@@ -168,7 +168,7 @@
" 1 | \n",
" 1 | \n",
" 0 | \n",
- " 19 | \n",
+ " 17 | \n",
" IonotropicSynapse | \n",
" 0 | \n",
" 0.25 | \n",
@@ -183,11 +183,11 @@
" 2 | \n",
" 2 | \n",
" 0 | \n",
- " 20 | \n",
+ " 23 | \n",
" IonotropicSynapse | \n",
" 0 | \n",
" 0.25 | \n",
- " 0.25 | \n",
+ " 0.75 | \n",
" 0.0001 | \n",
" 0.0 | \n",
" 0.025 | \n",
@@ -198,11 +198,11 @@
" 3 | \n",
" 3 | \n",
" 4 | \n",
- " 12 | \n",
+ " 15 | \n",
" IonotropicSynapse | \n",
" 0 | \n",
" 0.25 | \n",
- " 0.25 | \n",
+ " 0.75 | \n",
" 0.0001 | \n",
" 0.0 | \n",
" 0.025 | \n",
@@ -213,7 +213,7 @@
" 4 | \n",
" 4 | \n",
" 4 | \n",
- " 16 | \n",
+ " 18 | \n",
" IonotropicSynapse | \n",
" 0 | \n",
" 0.25 | \n",
@@ -228,11 +228,11 @@
" 5 | \n",
" 5 | \n",
" 4 | \n",
- " 21 | \n",
+ " 22 | \n",
" IonotropicSynapse | \n",
" 0 | \n",
" 0.25 | \n",
- " 0.75 | \n",
+ " 0.25 | \n",
" 0.0001 | \n",
" 0.0 | \n",
" 0.025 | \n",
@@ -243,11 +243,11 @@
" 6 | \n",
" 6 | \n",
" 8 | \n",
- " 13 | \n",
+ " 14 | \n",
" IonotropicSynapse | \n",
" 0 | \n",
" 0.25 | \n",
- " 0.75 | \n",
+ " 0.25 | \n",
" 0.0001 | \n",
" 0.0 | \n",
" 0.025 | \n",
@@ -258,11 +258,11 @@
" 7 | \n",
" 7 | \n",
" 8 | \n",
- " 17 | \n",
+ " 18 | \n",
" IonotropicSynapse | \n",
" 0 | \n",
" 0.25 | \n",
- " 0.75 | \n",
+ " 0.25 | \n",
" 0.0001 | \n",
" 0.0 | \n",
" 0.025 | \n",
@@ -273,11 +273,11 @@
" 8 | \n",
" 8 | \n",
" 8 | \n",
- " 21 | \n",
+ " 20 | \n",
" IonotropicSynapse | \n",
" 0 | \n",
" 0.25 | \n",
- " 0.75 | \n",
+ " 0.25 | \n",
" 0.0001 | \n",
" 0.0 | \n",
" 0.025 | \n",
@@ -290,26 +290,26 @@
],
"text/plain": [
" global_edge_index pre_global_comp_index post_global_comp_index \\\n",
- "0 0 0 13 \n",
- "1 1 0 19 \n",
- "2 2 0 20 \n",
- "3 3 4 12 \n",
- "4 4 4 16 \n",
- "5 5 4 21 \n",
- "6 6 8 13 \n",
- "7 7 8 17 \n",
- "8 8 8 21 \n",
+ "0 0 0 12 \n",
+ "1 1 0 17 \n",
+ "2 2 0 23 \n",
+ "3 3 4 15 \n",
+ "4 4 4 18 \n",
+ "5 5 4 22 \n",
+ "6 6 8 14 \n",
+ "7 7 8 18 \n",
+ "8 8 8 20 \n",
"\n",
" type type_ind pre_locs post_locs IonotropicSynapse_gS \\\n",
- "0 IonotropicSynapse 0 0.25 0.75 0.0001 \n",
+ "0 IonotropicSynapse 0 0.25 0.25 0.0001 \n",
"1 IonotropicSynapse 0 0.25 0.75 0.0001 \n",
- "2 IonotropicSynapse 0 0.25 0.25 0.0001 \n",
- "3 IonotropicSynapse 0 0.25 0.25 0.0001 \n",
+ "2 IonotropicSynapse 0 0.25 0.75 0.0001 \n",
+ "3 IonotropicSynapse 0 0.25 0.75 0.0001 \n",
"4 IonotropicSynapse 0 0.25 0.25 0.0001 \n",
- "5 IonotropicSynapse 0 0.25 0.75 0.0001 \n",
- "6 IonotropicSynapse 0 0.25 0.75 0.0001 \n",
- "7 IonotropicSynapse 0 0.25 0.75 0.0001 \n",
- "8 IonotropicSynapse 0 0.25 0.75 0.0001 \n",
+ "5 IonotropicSynapse 0 0.25 0.25 0.0001 \n",
+ "6 IonotropicSynapse 0 0.25 0.25 0.0001 \n",
+ "7 IonotropicSynapse 0 0.25 0.25 0.0001 \n",
+ "8 IonotropicSynapse 0 0.25 0.25 0.0001 \n",
"\n",
" IonotropicSynapse_e_syn IonotropicSynapse_k_minus IonotropicSynapse_s \\\n",
"0 0.0 0.025 0.2 \n",
@@ -345,7 +345,7 @@
},
{
"cell_type": "markdown",
- "id": "c35637f5",
+ "id": "96bc984b",
"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",
@@ -356,7 +356,7 @@
{
"cell_type": "code",
"execution_count": 4,
- "id": "9cfd34e6",
+ "id": "0c9edfca",
"metadata": {},
"outputs": [],
"source": [
@@ -365,7 +365,7 @@
},
{
"cell_type": "markdown",
- "id": "ba4ed5b8",
+ "id": "11c161f2",
"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:"
@@ -374,7 +374,7 @@
{
"cell_type": "code",
"execution_count": 5,
- "id": "cf2902aa",
+ "id": "bae02484",
"metadata": {},
"outputs": [
{
@@ -403,7 +403,7 @@
},
{
"cell_type": "markdown",
- "id": "194124de",
+ "id": "50deb603",
"metadata": {},
"source": [
"### Example 1: Setting synaptic parameters which connect particular neurons"
@@ -411,7 +411,7 @@
},
{
"cell_type": "markdown",
- "id": "0aea923c",
+ "id": "ce364144",
"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",
@@ -422,7 +422,7 @@
{
"cell_type": "code",
"execution_count": 6,
- "id": "6d3ce515",
+ "id": "0e268eff",
"metadata": {},
"outputs": [],
"source": [
@@ -438,7 +438,7 @@
{
"cell_type": "code",
"execution_count": 7,
- "id": "bcd60d95",
+ "id": "eb0e685e",
"metadata": {},
"outputs": [
{
@@ -467,7 +467,7 @@
},
{
"cell_type": "markdown",
- "id": "4eab6004",
+ "id": "7224e99c",
"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:"
@@ -475,7 +475,7 @@
},
{
"cell_type": "markdown",
- "id": "a05bfa60",
+ "id": "4644a07c",
"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",
@@ -486,7 +486,7 @@
},
{
"cell_type": "markdown",
- "id": "09572528",
+ "id": "ecb7f210",
"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`."
@@ -494,7 +494,7 @@
},
{
"cell_type": "markdown",
- "id": "4c710e44",
+ "id": "0fb76219",
"metadata": {},
"source": [
"Next, we take `.edges`, which is a [pandas DataFrame](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html):\n",
@@ -505,7 +505,7 @@
},
{
"cell_type": "markdown",
- "id": "24c7f242",
+ "id": "c92c8f1a",
"metadata": {},
"source": [
"We then modify this DataFrame to only contain those rows where the global cell index is in 0 or 1:\n",
@@ -516,7 +516,7 @@
},
{
"cell_type": "markdown",
- "id": "0c0ee839",
+ "id": "16640ed8",
"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[\"pre_global_cell_index\"].isin([0, 1])]`.\n",
@@ -529,7 +529,7 @@
},
{
"cell_type": "markdown",
- "id": "7a2db8c6",
+ "id": "84359619",
"metadata": {},
"source": [
"### Example 2: Setting parameters given pre- and post-synaptic cell indices"
@@ -537,7 +537,7 @@
},
{
"cell_type": "markdown",
- "id": "33a79f6d",
+ "id": "608c7fe0",
"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."
@@ -546,7 +546,7 @@
{
"cell_type": "code",
"execution_count": 8,
- "id": "343a5bb6",
+ "id": "8a926b4b",
"metadata": {},
"outputs": [],
"source": [
@@ -556,7 +556,7 @@
},
{
"cell_type": "markdown",
- "id": "9bd83ab7",
+ "id": "791f85e7",
"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:"
@@ -565,7 +565,7 @@
{
"cell_type": "code",
"execution_count": 9,
- "id": "34855241",
+ "id": "7402688c",
"metadata": {},
"outputs": [],
"source": [
@@ -580,7 +580,7 @@
{
"cell_type": "code",
"execution_count": 10,
- "id": "58514a0f",
+ "id": "e9e218a8",
"metadata": {},
"outputs": [
{
@@ -609,7 +609,7 @@
},
{
"cell_type": "markdown",
- "id": "9fa849be",
+ "id": "b26910a6",
"metadata": {},
"source": [
"### Example 3: Applying this strategy to cell level parameters"
@@ -617,7 +617,7 @@
},
{
"cell_type": "markdown",
- "id": "fe6be17f",
+ "id": "286437e9",
"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:"
@@ -626,7 +626,7 @@
{
"cell_type": "code",
"execution_count": 11,
- "id": "5945b258",
+ "id": "e7df53fd",
"metadata": {},
"outputs": [],
"source": [
@@ -640,7 +640,7 @@
},
{
"cell_type": "markdown",
- "id": "ea91ca1e",
+ "id": "ad2c218a",
"metadata": {},
"source": [
"### Example 4: Flexibly setting parameters based on their `groups`"
@@ -648,7 +648,7 @@
},
{
"cell_type": "markdown",
- "id": "b8785888",
+ "id": "2a026a2d",
"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):"
@@ -657,7 +657,7 @@
{
"cell_type": "code",
"execution_count": 12,
- "id": "073c2612",
+ "id": "a3787bbb",
"metadata": {},
"outputs": [],
"source": [
@@ -670,7 +670,7 @@
},
{
"cell_type": "markdown",
- "id": "57b9343a",
+ "id": "02b24c9e",
"metadata": {},
"source": [
"Now, say we want all synapses that start from these excitatory neurons. You can do this as follows:"
@@ -679,7 +679,7 @@
{
"cell_type": "code",
"execution_count": 13,
- "id": "6be209b1",
+ "id": "5eecadf8",
"metadata": {},
"outputs": [],
"source": [
@@ -695,7 +695,7 @@
},
{
"cell_type": "markdown",
- "id": "3fd67f11",
+ "id": "e3fc0c21",
"metadata": {},
"source": [
"### Example 5: Setting synaptic parameters based on properties of the presynaptic cell"
@@ -703,7 +703,7 @@
},
{
"cell_type": "markdown",
- "id": "223b04e2",
+ "id": "336f4727",
"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:"
@@ -712,7 +712,7 @@
{
"cell_type": "code",
"execution_count": 14,
- "id": "ff757547",
+ "id": "9fbda21b",
"metadata": {},
"outputs": [],
"source": [
@@ -725,7 +725,7 @@
},
{
"cell_type": "markdown",
- "id": "1481d591",
+ "id": "a341d180",
"metadata": {},
"source": [
"Now, let us query which cells have the desired synapses:"
@@ -734,7 +734,7 @@
{
"cell_type": "code",
"execution_count": 15,
- "id": "84520493",
+ "id": "c319f344",
"metadata": {},
"outputs": [],
"source": [
@@ -745,7 +745,7 @@
},
{
"cell_type": "markdown",
- "id": "e22b558c",
+ "id": "9594dfb2",
"metadata": {},
"source": [
"`indices_of_sodium_compartments` lists all compartments which contained sodium:"
@@ -754,7 +754,7 @@
{
"cell_type": "code",
"execution_count": 16,
- "id": "b8f35873",
+ "id": "950fccb7",
"metadata": {},
"outputs": [
{
@@ -771,7 +771,7 @@
},
{
"cell_type": "markdown",
- "id": "40274381",
+ "id": "b9a6317d",
"metadata": {},
"source": [
"Then, we can proceed as always and filter for the global pre-synaptic **compartment** index:"
@@ -779,8 +779,8 @@
},
{
"cell_type": "code",
- "execution_count": 18,
- "id": "bda373bc",
+ "execution_count": 17,
+ "id": "d8bcd677",
"metadata": {},
"outputs": [],
"source": [
@@ -791,8 +791,8 @@
},
{
"cell_type": "code",
- "execution_count": 19,
- "id": "c1fcf3dc",
+ "execution_count": 18,
+ "id": "e51a3a46",
"metadata": {},
"outputs": [
{
@@ -810,7 +810,7 @@
"Name: IonotropicSynapse_gS, dtype: float64"
]
},
- "execution_count": 19,
+ "execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
@@ -821,7 +821,7 @@
},
{
"cell_type": "markdown",
- "id": "f111f537",
+ "id": "2389a302",
"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)."
@@ -829,7 +829,7 @@
},
{
"cell_type": "markdown",
- "id": "b7872d80",
+ "id": "4d3c37e5",
"metadata": {},
"source": [
"### Summary\n",
diff --git a/docs/tutorials/10_advanced_parameter_sharing.ipynb b/docs/tutorials/10_advanced_parameter_sharing.ipynb
index db9d826e..935fd7cf 100644
--- a/docs/tutorials/10_advanced_parameter_sharing.ipynb
+++ b/docs/tutorials/10_advanced_parameter_sharing.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "5f0bc78a",
+ "id": "f3b61d61",
"metadata": {},
"source": [
"# Synaptic parameter sharing"
@@ -10,7 +10,7 @@
},
{
"cell_type": "markdown",
- "id": "7ca7f94a",
+ "id": "4dcc69e0",
"metadata": {},
"source": [
"In this tutorial, you will learn how to:\n",
@@ -37,7 +37,7 @@
},
{
"cell_type": "markdown",
- "id": "422006f3",
+ "id": "74b4d1a0",
"metadata": {},
"source": [
"In a [previous tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/07_gradient_descent.html) about training networks, we briefly touched on parameter sharing. In this tutorial, we will show you how you can flexibly share parameters within a network."
@@ -46,7 +46,7 @@
{
"cell_type": "code",
"execution_count": 1,
- "id": "4feb39c3",
+ "id": "82a50f5b",
"metadata": {},
"outputs": [],
"source": [
@@ -58,7 +58,7 @@
},
{
"cell_type": "markdown",
- "id": "7c18b422",
+ "id": "fa8523c7",
"metadata": {},
"source": [
"### Preface: Building the network\n",
@@ -69,7 +69,7 @@
{
"cell_type": "code",
"execution_count": 2,
- "id": "5b3dacee",
+ "id": "34d12c10",
"metadata": {},
"outputs": [],
"source": [
@@ -85,7 +85,7 @@
},
{
"cell_type": "markdown",
- "id": "7c1e73e0",
+ "id": "5951dcc1",
"metadata": {},
"source": [
"### Sharing parameters by modifying `controlled_by_param`"
@@ -94,7 +94,7 @@
{
"cell_type": "code",
"execution_count": 3,
- "id": "c94aa7f7",
+ "id": "c3b673f4",
"metadata": {},
"outputs": [
{
@@ -119,7 +119,7 @@
},
{
"cell_type": "markdown",
- "id": "75aded8e",
+ "id": "51e66885",
"metadata": {},
"source": [
"Let's look at this line by line. First, we exactly follow the previous tutorial in selecting the synapses which we are interested in training (i.e., the ones whose presynaptic neuron has index 0, 1, 2):"
@@ -128,7 +128,7 @@
{
"cell_type": "code",
"execution_count": 4,
- "id": "3d73ce97",
+ "id": "2cc62f44",
"metadata": {},
"outputs": [],
"source": [
@@ -139,7 +139,7 @@
},
{
"cell_type": "markdown",
- "id": "0d8a9f19",
+ "id": "0cde33fe",
"metadata": {},
"source": [
"As second step, we enable parameter sharing. This is done by setting the `controlled_by_param`. Synapses that have the same value in `controlled_by_param` will be shared. Let's inspect `controlled_by_param` _before_ we modify it:"
@@ -148,7 +148,7 @@
{
"cell_type": "code",
"execution_count": 5,
- "id": "5be614a3",
+ "id": "d1077cd8",
"metadata": {},
"outputs": [
{
@@ -250,7 +250,7 @@
},
{
"cell_type": "markdown",
- "id": "f5e8b81a",
+ "id": "48133c83",
"metadata": {},
"source": [
"Every synapse has a different value. Because of this, no synaptic parameters will be shared. To enable parameter sharing we override the `controlled_by_param` column with the presynaptic cell index:"
@@ -259,7 +259,7 @@
{
"cell_type": "code",
"execution_count": 6,
- "id": "f22af5fe",
+ "id": "6e2545bb",
"metadata": {},
"outputs": [],
"source": [
@@ -270,7 +270,7 @@
{
"cell_type": "code",
"execution_count": 7,
- "id": "7f88d535",
+ "id": "1f5daaeb",
"metadata": {},
"outputs": [
{
@@ -372,7 +372,7 @@
},
{
"cell_type": "markdown",
- "id": "cef2bed9",
+ "id": "5649f0bb",
"metadata": {},
"source": [
"Now, all we have to do is to make these synaptic parameters trainable with the `make_trainable()` method:"
@@ -381,7 +381,7 @@
{
"cell_type": "code",
"execution_count": 8,
- "id": "f3d3ce72",
+ "id": "7445eeed",
"metadata": {},
"outputs": [
{
@@ -398,7 +398,7 @@
},
{
"cell_type": "markdown",
- "id": "4da29681",
+ "id": "9a640047",
"metadata": {},
"source": [
"It correctly says that we added three parameters (because we have three cells, and we share individual synaptic parameters). We now have 6 trainable parameters in total (because we already added 3 trainable parameters above)."
@@ -406,7 +406,7 @@
},
{
"cell_type": "markdown",
- "id": "1c902a3e",
+ "id": "3a224a36",
"metadata": {},
"source": [
"### A more involved example: sharing by pre- and post-synaptic cell type\n",
@@ -417,7 +417,7 @@
{
"cell_type": "code",
"execution_count": 9,
- "id": "af856a23",
+ "id": "a30757f0",
"metadata": {},
"outputs": [],
"source": [
@@ -427,7 +427,7 @@
{
"cell_type": "code",
"execution_count": 10,
- "id": "642245db",
+ "id": "628b7728",
"metadata": {},
"outputs": [],
"source": [
@@ -441,7 +441,7 @@
},
{
"cell_type": "markdown",
- "id": "b11c9625",
+ "id": "672bfa13",
"metadata": {},
"source": [
"We want to make all synapses that start from excitatory or inhibitory neurons trainable. In addition, we want to use the same parameter for synapses if they have the same pre- **and** post-synaptic cell type."
@@ -449,7 +449,7 @@
},
{
"cell_type": "markdown",
- "id": "7ebcfedd",
+ "id": "22d348f2",
"metadata": {},
"source": [
"To achieve this, we will first want a column in `net.nodes` which indicates the cell type. "
@@ -457,19 +457,18 @@
},
{
"cell_type": "code",
- "execution_count": 11,
- "id": "3e587ba0",
+ "execution_count": 12,
+ "id": "e1778532",
"metadata": {},
"outputs": [],
"source": [
- "for group, inds in net.groups.items():\n",
- " net.nodes.loc[inds, \"cell_type\"] = group"
+ "net.nodes[\"cell_type\"] = net.nodes[[\"exc\", \"inh\", \"unknown\"]].idxmax(axis=1)"
]
},
{
"cell_type": "code",
- "execution_count": 12,
- "id": "3d0d7d8f",
+ "execution_count": 14,
+ "id": "620a6331",
"metadata": {},
"outputs": [
{
@@ -502,7 +501,7 @@
"Name: cell_type, dtype: object"
]
},
- "execution_count": 12,
+ "execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
@@ -513,7 +512,7 @@
},
{
"cell_type": "markdown",
- "id": "c5675586",
+ "id": "04f820d6",
"metadata": {},
"source": [
"The `cell_type` is now part of the `net.nodes`. However, we would like to do parameter sharing of synapses based on the pre- and post-synaptic node values. To do so, we import the `cell_type` column into `net.edges`. To do this, we use the `.copy_node_property_to_edges()` which the name of the property you are copying from nodes: "
@@ -521,8 +520,8 @@
},
{
"cell_type": "code",
- "execution_count": 13,
- "id": "a521b569",
+ "execution_count": 15,
+ "id": "45e0b1eb",
"metadata": {},
"outputs": [],
"source": [
@@ -531,7 +530,7 @@
},
{
"cell_type": "markdown",
- "id": "dbbf82e5",
+ "id": "791a3345",
"metadata": {},
"source": [
"After this, you have columns in the **`.edges`** which indicate the pre- and post-synaptic cell type:"
@@ -539,8 +538,8 @@
},
{
"cell_type": "code",
- "execution_count": 14,
- "id": "91bfd2ca",
+ "execution_count": 16,
+ "id": "8755607c",
"metadata": {},
"outputs": [
{
@@ -793,7 +792,7 @@
"35 unknown unknown"
]
},
- "execution_count": 14,
+ "execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
@@ -804,7 +803,7 @@
},
{
"cell_type": "markdown",
- "id": "0f96f368",
+ "id": "9a4b6626",
"metadata": {},
"source": [
"Next, we specify which parts of the network we actually want to change (in this case, all synapses which have excitatory or inhibitory presynaptic neurons):"
@@ -812,8 +811,8 @@
},
{
"cell_type": "code",
- "execution_count": 15,
- "id": "d5beeeae",
+ "execution_count": 17,
+ "id": "c0023aec",
"metadata": {},
"outputs": [
{
@@ -834,7 +833,7 @@
},
{
"cell_type": "markdown",
- "id": "920a141b",
+ "id": "718093e1",
"metadata": {},
"source": [
"As the last step, we again have to specify parameter sharing by setting `controlled_by_param`. In this case, we want to share parameters that have the same pre- and post-synaptic neuron. We achieve this by **grouping** the synpases by their pre- and post-synaptic cell type (see [pd.DataFrame.groupby](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.groupby.html) for details):"
@@ -842,8 +841,8 @@
},
{
"cell_type": "code",
- "execution_count": 16,
- "id": "320e2938",
+ "execution_count": 18,
+ "id": "0b19e4ac",
"metadata": {},
"outputs": [
{
@@ -862,7 +861,7 @@
},
{
"cell_type": "markdown",
- "id": "bffb1286",
+ "id": "f5a65a8a",
"metadata": {},
"source": [
"This created six trainable parameters, which makes sense as we have two types of pre-synaptic neurons (excitatory and inhibitory) and each has three options for the postsynaptic neuron (pre, post, unknown)."
@@ -870,7 +869,7 @@
},
{
"cell_type": "markdown",
- "id": "d9992480",
+ "id": "5486a859",
"metadata": {},
"source": [
"### Summary\n",
diff --git a/jaxley/io/graph.py b/jaxley/io/graph.py
index 19f89703..aed9ec20 100644
--- a/jaxley/io/graph.py
+++ b/jaxley/io/graph.py
@@ -789,7 +789,8 @@ def from_graph(
.apply(lambda x: x.index.values, include_groups=False)
.to_dict()
)
- module.groups = groups
+ for group_name, group_inds in groups.items():
+ module.select(nodes=group_inds).add_to_group(group_name)
node_df.columns = [
"global_" + col if "local" not in col and "index" in col else col
@@ -866,17 +867,7 @@ def to_graph(
for col in nodes.columns: # col wise adding preserves dtypes
module_graph.add_nodes_from(nodes[[col]].to_dict(orient="index").items())
- nx.set_node_attributes(module_graph, [], "groups")
- if len(module.groups) > 0:
- groups_dict = {
- index: {
- "groups": [
- key for key, value in module.groups.items() if index in value
- ]
- }
- for index in range(max(map(max, module.groups.values())) + 1)
- }
- module_graph.add_nodes_from(groups_dict.items())
+ module_graph.graph["group_names"] = module.group_names
inter_branch_edges = module.branch_edges.copy()
intra_branch_edges = []
diff --git a/jaxley/modules/base.py b/jaxley/modules/base.py
index 46f06522..5c1ee0f1 100644
--- a/jaxley/modules/base.py
+++ b/jaxley/modules/base.py
@@ -118,7 +118,7 @@ def __init__(self):
self.total_nbranches: int = 0
self.nbranches_per_cell: List[int] = None
- self.groups = {}
+ self.group_names: List[str] = []
self.nodes: Optional[pd.DataFrame] = None
self._scope = "local" # defaults to local scope
@@ -205,12 +205,9 @@ def __getattr__(self, key):
return super().__getattribute__(key)
# intercepts calls to groups
- if key in self.base.groups:
- view = (
- self.select(self.groups[key])
- if key in self.groups
- else self.select(None)
- )
+ if key in self.base.group_names:
+ inds = self.nodes.index[self.nodes[key]].to_numpy()
+ view = self.select(inds)
view._set_controlled_by_param(key)
return view
@@ -257,7 +254,7 @@ def __getitem__(self, index):
"""Lazy indexing of the module."""
supported_parents = ["network", "cell", "branch"] # cannot index into comp
- not_group_view = self._current_view not in self.groups
+ not_group_view = self._current_view not in self.group_names
assert (
self._current_view in supported_parents or not_group_view
), "Lazy indexing is only supported for `Network`, `Cell`, `Branch` and Views thereof."
@@ -929,6 +926,8 @@ def set_ncomp(
that is modified.
- When the lengths of the compartments are not the same within the branch
that is modified.
+ - When the branch that is modified has compartments belonging to different
+ groups.
- Unless the morphology was read from an SWC file, when the radiuses of the
compartments are not the same within the branch that is modified.
"""
@@ -997,6 +996,16 @@ def set_ncomp(
"`.set_ncomp()` and then insert the channels accordingly."
)
+ for group_name in self.group_names:
+ group_ncomp = view[group_name].sum()
+ assert group_ncomp == 0 or group_ncomp == num_previous_ncomp, (
+ f"{group_ncomp} compartments within the branch are part of the "
+ f"group '{group_name}', but the other "
+ f"{num_previous_ncomp - group_ncomp} compartments are not. This "
+ f"is not allowed: Every compartment must belong to the same group for "
+ f"`.set_ncomp()` to work."
+ )
+
# Add new rows as the average of all rows. Special case for the length is below.
average_row = self.nodes.mean(skipna=False)
average_row = average_row.to_frame().T
@@ -1007,8 +1016,8 @@ def set_ncomp(
integer_cols = ["global_cell_index", "global_branch_index", "global_comp_index"]
view[integer_cols] = view[integer_cols].astype(int)
- # Whether or not a channel exists in a compartment is a boolean.
- boolean_cols = channel_names
+ # Whether or not a channel or group exists in a compartment is a boolean.
+ boolean_cols = channel_names + self.base.group_names
view[boolean_cols] = view[boolean_cols].astype(bool)
# Special treatment for the lengths and radiuses. These are not being set as
@@ -1242,12 +1251,12 @@ def add_to_group(self, group_name: str):
Args:
group_name: The name of the group.
"""
- if group_name not in self.base.groups:
- self.base.groups[group_name] = self._nodes_in_view
+ if group_name not in self.base.group_names:
+ self.base.group_names.append(group_name)
+ self.base.nodes[group_name] = False
+ self.base.nodes.loc[self._nodes_in_view, group_name] = True
else:
- self.base.groups[group_name] = np.unique(
- np.concatenate([self.base.groups[group_name], self._nodes_in_view])
- )
+ self.base.nodes.loc[self._nodes_in_view, group_name] = True
def _get_state_names(self) -> Tuple[List, List]:
"""Collect all recordable / clampable states in the membrane and synapses.
@@ -2721,9 +2730,7 @@ def __init__(
self.ncomp_per_branch = pointer.base.ncomp_per_branch[self._branches_in_view]
self.comb_parents = self.base.comb_parents[self._branches_in_view]
self._set_externals_in_view()
- self.groups = {
- k: np.intersect1d(v, self._nodes_in_view) for k, v in pointer.groups.items()
- }
+ self.group_names = self.base.group_names
self.jaxnodes, self.jaxedges = self._jax_arrays_in_view(
pointer
diff --git a/jaxley/utils/plot_utils.py b/jaxley/utils/plot_utils.py
index dea72bc1..f4c06828 100644
--- a/jaxley/utils/plot_utils.py
+++ b/jaxley/utils/plot_utils.py
@@ -378,7 +378,7 @@ def plot_comps(
module_or_view.nodes["global_branch_index"] == idx
]
for l, axis, (i, comp) in zip(cylinder_lens, axes, branch_df.iterrows()):
- center = comp[["x", "y", "z"]]
+ center = comp[["x", "y", "z"]].astype(float)
radius = comp["radius"]
length = comp["length"] if true_comp_length else l
xyz = create_cylinder_mesh(length, radius, resolution)
diff --git a/tests/test_graph.py b/tests/test_graph.py
index e49642a8..a1d012ee 100644
--- a/tests/test_graph.py
+++ b/tests/test_graph.py
@@ -86,9 +86,8 @@ def test_graph_import_export_cycle(
equal_both_nan_or_empty_df(re_module.branch_edges, module.branch_edges)
)
- for k in module.groups:
- assert k in re_module.groups
- assert np.all(re_module.groups[k] == module.groups[k])
+ for k in module.group_names:
+ assert k in re_module.group_names
for re_xyzr, xyzr in zip(re_module.xyzr, module.xyzr):
re_xyzr[np.isnan(re_xyzr)] = -1
diff --git a/tests/test_groups.py b/tests/test_groups.py
index 8fd3cfee..413ee327 100644
--- a/tests/test_groups.py
+++ b/tests/test_groups.py
@@ -54,6 +54,7 @@ def test_subclassing_groups_net_set_equivalence(SimpleNet):
net2.cell([0, 5]).branch(1).comp("all").set("length", 0.16)
net2.cell([0, 3, 5]).branch(1).comp(2).set("axial_resistivity", 1100.0)
+ net1.nodes.drop(columns=["excitatory"], inplace=True)
assert all(net1.nodes == net2.nodes)
@@ -107,3 +108,15 @@ def test_fully_connect_groups_equivalence(SimpleNet):
fully_connect(pre, post, IonotropicSynapse())
assert all(net1.edges == net2.edges)
+
+
+def test_set_ncomp_changes_groups(SimpleCell):
+ """Test whether groups get updated appropriately after `set_ncomp`."""
+ cell = SimpleCell(3, 4)
+ cell.branch(0).add_to_group("exc")
+ cell.branch(0).set_ncomp(1)
+ assert len(cell.exc.nodes) == 1
+
+ cell.branch(1).add_to_group("exc")
+ cell.branch(0).set_ncomp(2)
+ assert len(cell.exc.nodes) == 6 # 2 from branch(0) and 4 from branch(1).
diff --git a/tests/test_swc.py b/tests/test_swc.py
index 654f8bdc..eb78c54b 100644
--- a/tests/test_swc.py
+++ b/tests/test_swc.py
@@ -267,19 +267,29 @@ def test_swc_types(reader_backend, file):
{"ignore_swc_trace_errors": False} if reader_backend == "graph" else {}
)
cell = jx.read_swc(fname, ncomp=1, backend=reader_backend, **backend_kwargs)
- desired_numbers_of_comps = {
- "morph_3_types.swc": {"soma": 1, "axon": 1, "basal": 1},
- "morph_3_types_single_point_soma.swc": {
- "soma": 1,
- "axon": 1,
- "basal": 1,
- },
- "morph.swc": {"soma": 2, "basal": 101, "apical": 53},
- "bbp_with_axon.swc": {"soma": 1, "axon": 128, "basal": 66, "apical": 129},
- }
- # Test soma.
- for key, n_desired in desired_numbers_of_comps[file].items():
- n_comps_in_morph = len(cell.groups[key])
- assert (
- n_comps_in_morph == n_desired
- ), f"{key} has {n_comps_in_morph} != {n_desired} comps!"
+
+ # First iteration is with default `ncomp`. At the end of the first loop we change
+ # ncomp with `set_ncomp`
+ for i in range(2):
+ desired_numbers_of_comps = {
+ "morph_3_types.swc": {"soma": 1, "axon": 1, "basal": 1},
+ "morph_3_types_single_point_soma.swc": {
+ "soma": 1,
+ "axon": 1,
+ "basal": 1,
+ },
+ "morph.swc": {"soma": 2, "basal": 101, "apical": 53},
+ "bbp_with_axon.swc": {"soma": 1, "axon": 128, "basal": 66, "apical": 129},
+ }
+ # Test soma.
+ for key, n_desired in desired_numbers_of_comps[file].items():
+ if i == 1 and key in ["soma", "basal"]:
+ n_desired += 2 # After `set_ncomp` we should have two more comps.
+ n_comps_in_morph = len(cell.__getattr__(key).nodes)
+ assert (
+ n_comps_in_morph == n_desired
+ ), f"{key} has {n_comps_in_morph} != {n_desired} comps!"
+
+ # Additional tests to ensure that `groups` get updated appropriately.
+ cell.soma.branch(0).set_ncomp(3)
+ cell.basal.branch(0).set_ncomp(3)