From bff1e3417e1e1da6132e89abf7da4d2a9a8adbc3 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Fri, 23 May 2025 16:55:24 +0200 Subject: [PATCH 01/24] wip: save wip for new graph reader --- dev.ipynb | 1109 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1109 insertions(+) create mode 100644 dev.ipynb diff --git a/dev.ipynb b/dev.ipynb new file mode 100644 index 000000000..ab45c19b7 --- /dev/null +++ b/dev.ipynb @@ -0,0 +1,1109 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %load_ext autoreload\n", + "# %autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from jax import config\n", + "config.update(\"jax_enable_x64\", True)\n", + "config.update(\"jax_platform_name\", \"cpu\")\n", + "\n", + "import os\n", + "os.environ[\"XLA_PYTHON_CLIENT_MEM_FRACTION\"]=\".8\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from __future__ import annotations\n", + "import jax\n", + "import jax.numpy as jnp\n", + "import equinox as eqx\n", + "import pandas as pd\n", + "\n", + "import networkx as nx\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from jax import vmap\n", + "# from graphjax.graph import MorphTree\n", + "\n", + "from typing import Optional, List, Dict, Any, Union, Set, Tuple\n", + "from dataclasses import dataclass, field" + ] + }, + { + "cell_type": "code", + "execution_count": 834, + "metadata": {}, + "outputs": [], + "source": [ + "def swc_to_morph_tree(fname: str, num_lines: Optional[int] = None) -> MorphTree:\n", + " i_id_xyzr_p = jnp.array(np.loadtxt(fname)[:num_lines])\n", + " \n", + " edges = i_id_xyzr_p[:, [0, -1]]\n", + " edges = edges[edges[:, 1] != -1].astype(int)\n", + " \n", + " nodes = i_id_xyzr_p[:, 0].astype(int)\n", + " \n", + " get_node_attrs = lambda id, x, y, z, r: {\"id\": int(id), \"x\": x, \"y\": y, \"z\": z, \"r\": r}\n", + " node_attrs = list(map(get_node_attrs, *i_id_xyzr_p[:, 1:-1].T)) \n", + " return MorphTree(nodes, edges, node_attrs)\n", + "\n", + "@dataclass\n", + "class MorphTree:\n", + " nodes: jnp.ndarray\n", + " edges: jnp.ndarray\n", + " node_attrs: List[Dict[str, Any]] = None\n", + " edge_attrs: List[Dict[str, Any]] = None\n", + " global_attrs: Dict[str, Any] = field(default_factory=dict)\n", + "\n", + " def __post_init__(self) -> None:\n", + " if self.node_attrs is None:\n", + " self.node_attrs = [{}]*len(self.nodes)\n", + " if self.edge_attrs is None:\n", + " self.edge_attrs = [{}]*len(self.edges)\n", + "\n", + " def __repr__(self) -> str:\n", + " n_nodes = len(self.nodes)\n", + " n_edges = len(self.edges)\n", + "\n", + " node_attrs = list(self.node_attrs[0].keys()) if len(self.node_attrs) > 0 else []\n", + " edge_attrs = list(self.edge_attrs[0].keys()) if len(self.edge_attrs) > 0 else []\n", + " return f\"MorphTree(nodes={n_nodes}*{node_attrs}, edges={n_edges}*{edge_attrs})\"\n", + " \n", + " def to_nx(self) -> nx.DiGraph:\n", + " G = nx.DiGraph()\n", + " node_map = map(int, self.nodes)\n", + " edge_map = map(lambda x: tuple(map(int, x)), self.edges.T)\n", + " G.add_nodes_from(zip(node_map, self.node_attrs))\n", + " G.add_edges_from(zip(*edge_map, self.edge_attrs))\n", + " return G\n", + " \n", + " @staticmethod\n", + " def from_nx(G: nx.DiGraph) -> MorphTree:\n", + " nodes = jnp.array(list(G.nodes))\n", + " edges = jnp.array(list(G.edges))\n", + " node_attrs = [G.nodes[n] for n in G.nodes]\n", + " edge_attrs = [G.edges[e] for e in G.edges]\n", + " return MorphTree(nodes, edges, node_attrs, edge_attrs)\n", + " \n", + " def to_pandas(self) -> Tuple[pd.DataFrame, pd.DataFrame]:\n", + " node_df = pd.DataFrame(self.node_attrs, index=np.array(self.nodes))\n", + " edge_df = pd.DataFrame(self.edge_attrs)\n", + " edge_index = pd.MultiIndex.from_arrays(np.array(self.edges).T)\n", + " edge_df = edge_df.set_index(edge_index)\n", + " return node_df, edge_df\n", + " \n", + " @staticmethod\n", + " def from_pandas(node_df: pd.DataFrame, edge_df: pd.DataFrame) -> MorphTree:\n", + " node_attrs = node_df.to_dict(orient=\"records\")\n", + " edge_attrs = edge_df.to_dict(orient=\"records\")\n", + " edges = edge_df.index.to_numpy()\n", + " nodes = node_df.index.to_numpy()\n", + " return MorphTree(nodes, edges, node_attrs, edge_attrs)\n", + " \n", + " def plot(self, **kwargs: Any) -> None:\n", + " G = self.to_nx()\n", + " pos = {}\n", + " for n, attr in G.nodes(data=True):\n", + " if \"x\" in attr: # assume y is also present\n", + " pos[n] = (attr[\"x\"], attr[\"y\"])\n", + " nx.draw(G, pos, with_labels=True, **kwargs)\n", + " plt.show()\n", + "\n", + " def reindex_nodes(self, new_indices: jnp.ndarray) -> MorphTree:\n", + " def remap(x: int) -> int:\n", + " idx = jnp.argmax(self.nodes == x)\n", + " exists = self.nodes[idx] == x\n", + " return jnp.where(exists, new_indices[idx], x)\n", + "\n", + " new_nodes = vmap(remap)(self.nodes.ravel()).reshape(self.nodes.shape)\n", + " new_edges = vmap(remap)(self.edges.ravel()).reshape(self.edges.shape)\n", + " return MorphTree(new_nodes, new_edges, self.node_attrs, self.edge_attrs)\n", + " \n", + " def reorder_tree(self, new_order: jnp.ndarray) -> MorphTree:\n", + " # TODO: check this does what I think it does, i.e. change the edge orientation\n", + " # in order of appearance of the nodes in self.nodes.\n", + " new_nodes = self.nodes[new_order]\n", + " new_tree = self.reindex_nodes(new_nodes)\n", + "\n", + " new_edges = new_tree.edges\n", + " idx_i = jnp.where(new_edges[:,0] == new_tree.nodes[:, None])[0]\n", + " idx_j = jnp.where(new_edges[:,1] == new_tree.nodes[:, None])[0]\n", + " is_descending = ~(idx_i < idx_j)[:, None]\n", + " ascending_edges = jnp.where(is_descending, new_edges[:, ::-1], new_edges)\n", + " return MorphTree(new_nodes, ascending_edges, new_tree.node_attrs, new_tree.edge_attrs)\n", + "\n", + "def list_branches(tree: MorphTree, return_branchpoints: bool = False) -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", + " G = tree.to_nx().to_undirected()\n", + " branches: List[List[int]] = []\n", + " branchpoints: Set[int] = set()\n", + " visited: Set[Tuple[int, int]] = set()\n", + "\n", + " def is_branchpoint(n: int) -> bool:\n", + " is_leaf = G.degree(n) <= 1\n", + " is_branching = G.degree(n) > 2\n", + " if G.degree(n) == 2:\n", + " i,j = G.neighbors(n)\n", + " # trace dir matters here! For segment with node IDs: [1, 1, 2, 2]\n", + " # -> [[1,1], [1,2,2]] \n", + " # <- [[2,2], [2,1,1]] \n", + " if is_soma(n):\n", + " return not same_id(n, j)\n", + " else:\n", + " # return not any([same_id(n, i), same_id(n, j)])\n", + " return not same_id(n, j)\n", + " \n", + " return is_leaf or is_branching\n", + "\n", + " def in_visited(n1: int, n2: int) -> bool:\n", + " return (n1, n2) in visited or (n2, n1) in visited\n", + "\n", + " def same_id(n1: int, n2: int) -> bool:\n", + " return G.nodes[n1][\"id\"] == G.nodes[n2][\"id\"] if \"id\" in G.nodes[n1] else True\n", + "\n", + " def is_soma(n: int) -> bool:\n", + " return G.nodes[n][\"id\"] == 1\n", + " \n", + " def soma_nodes() -> bool:\n", + " return [i for i, n in G.nodes.items() if n[\"id\"] == 1]\n", + "\n", + " def walk_path(start: int, succ: int) -> List[int]:\n", + " path = [start, succ]\n", + " visited.add((start, succ))\n", + " \n", + " while G.degree(succ) == 2:\n", + " next_node = next(n for n in G.neighbors(succ) if n != path[-2])\n", + "\n", + " if in_visited(succ, next_node) or is_branchpoint(succ):\n", + " break\n", + " \n", + " path.append(next_node)\n", + " visited.add((succ, next_node))\n", + " succ = next_node\n", + "\n", + " return path\n", + "\n", + " leaf = next(n for n in G.nodes if G.degree(n) == 1)\n", + " soma_nodes = soma_nodes()\n", + " for node in nx.dfs_tree(G, leaf):\n", + " if is_soma(node) and len(soma_nodes) == 1:\n", + " branches.append([node])\n", + "\n", + " elif is_branchpoint(node):\n", + " branchpoints.add(node)\n", + " for succ in G.neighbors(node):\n", + " if not in_visited(node, succ):\n", + " branches.append(walk_path(node, succ))\n", + " \n", + " if return_branchpoints:\n", + " branchpoint_edges = sum([list(G.edges(n)) for n in branchpoints], [])\n", + " return branches, branchpoints, branchpoint_edges\n", + " return branches\n", + "\n", + "# def compartmentalize(tree: MorphTree, num_comps: int = 1) -> MorphTree:\n", + "# branches = list_branches(tree)\n", + "# nodes_df, _ = tree.to_pandas()\n", + "# nodes_df = nodes_df.astype(float)\n", + "\n", + "# new_inds = len(branches)*num_comps\n", + "# existing_inds = set(nodes_df.index)\n", + "# proposed_new_inds = set(range(len(branches)*num_comps + len(existing_inds)))\n", + "# new_inds = list(proposed_new_inds.difference(existing_inds))\n", + " \n", + "# branch_nodes: List[np.ndarray] = []\n", + "# branch_edges: List[List[Tuple[int, int]]] = []\n", + "# for i, b in enumerate(branches):\n", + "# branch_node_attrs = nodes_df.loc[b]\n", + "# xyz_i = branch_node_attrs[[\"x\", \"y\", \"z\"]]\n", + "# pathlen = ((xyz_i.diff(axis=0).fillna(0)**2).sum(axis=1)**.5)\n", + "# branch_node_attrs[\"l\"] = pathlen.cumsum()\n", + "# v_interp = vmap(jnp.interp, in_axes=(None, None, 1), out_axes=1)\n", + "\n", + "# branch_len = max(branch_node_attrs[\"l\"])\n", + "# comp_len = branch_len / num_comps\n", + "# comp_locs = jnp.linspace(comp_len/2, branch_len - comp_len/2, num_comps)\n", + " \n", + "# x = jnp.array([0] + list(comp_locs) + [branch_len])\n", + "# xp = jnp.array(branch_node_attrs[\"l\"].values)\n", + "# fp = jnp.array(branch_node_attrs[[\"x\", \"y\", \"z\", \"r\"]].values)\n", + "\n", + "# tmp_inds = [b[0]] + new_inds[i:i+num_comps] + [b[-1]]\n", + "# types = [0] + [1]*num_comps + [0] # 0: branchpoint, 1: compartment\n", + "# branch_idx = [i]*(num_comps+2)\n", + "# comp_inds_and_type = np.array([tmp_inds, branch_idx, types]).T\n", + "# comp_xyzr = np.array(v_interp(x, xp, fp))\n", + "# comp_xyzr = np.hstack([comp_inds_and_type, comp_xyzr])\n", + "\n", + "# branch_edges.append([(i,j) for i,j in zip(tmp_inds[:-1], tmp_inds[1:])])\n", + "# branch_nodes.append(comp_xyzr)\n", + "\n", + "# branch_nodes = jnp.concatenate(branch_nodes)\n", + "# comp_attrs_keys = [\"idx\", \"branch\", \"type\", \"x\", \"y\", \"z\", \"r\"]\n", + "# comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", + "# comp_df[[\"idx\", \"branch\", \"type\"]] = comp_df[[\"idx\", \"branch\", \"type\"]].astype(int)\n", + " \n", + "# # drop duplicated branch nodes\n", + "# comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", + "# comp_df = comp_df.set_index(\"idx\")\n", + "\n", + "# comps = jnp.array(comp_df.index)\n", + "# comp_attrs = comp_df.to_dict(orient=\"records\")\n", + "# comp_edges = jnp.array(sum(branch_edges, []))\n", + "\n", + "# comp_tree = MorphTree(comps, comp_edges, comp_attrs)\n", + "# comp_tree = comp_tree.reindex_nodes(jnp.arange(len(comps)))\n", + "# return comp_tree" + ] + }, + { + "cell_type": "code", + "execution_count": 835, + "metadata": {}, + "outputs": [], + "source": [ + "class DummyChannel:\n", + " def __init__(self):\n", + " self.params = {\"gbar\": 1.0, \"e\": 0.0, \"nn_weights\": jnp.ones((10, 10))}\n", + " self.states = {\"m\": 0.5, \"h\": 0.5}\n", + "\n", + "def dummy_insert(tree, inds, channel):\n", + " # TODO: where to store the equiv of self.channels, i.e. in module or in tree.global_attrs?\n", + " # Should Module and MorphTree be separate or the same thing?\n", + " for i in inds:\n", + " tree.node_attrs[i].update(channel.params)\n", + " tree.node_attrs[i].update(channel.states)\n", + "\n", + "def dummy_set(tree, inds, key, value):\n", + " for i in inds:\n", + " tree.node_attrs[i][key] = value\n", + "\n", + "def dummy_to_pytree(tree):\n", + " nodes_df = tree.to_pandas()[0]\n", + " jax_nodes = {}\n", + " for key in nodes_df.columns:\n", + " values = jnp.array(nodes_df.loc[~nodes_df[key].isna(), key].to_list())\n", + " jax_nodes[key] = values\n", + " return jax_nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 859, + "metadata": {}, + "outputs": [], + "source": [ + "from jaxley.io.graph import build_compartment_graph, to_swc_graph, _trace_branches\n", + "\n", + "testcases = [ \n", + "\"morph_3_types_single_point_soma.swc\",\n", + "\"morph_3_types.swc\",\n", + "\"morph_interrupted_soma.swc\",\n", + "\"morph_soma_both_ends.swc\",\n", + "\"morph_somatic_branchpoint.swc\",\n", + "\"morph_non_somatic_branchpoint.swc\", # no soma!\n", + "\"morph_ca1_n120_single_point_soma.swc\",\n", + "\"morph_ca1_n120.swc\",\n", + "\"morph_l5pc_with_axon.swc\",\n", + "\"morph_allen_485574832.swc\",\n", + "]\n", + "\n", + "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[9])\n", + "\n", + "morph_branches = list_branches(MorphTree.from_nx(jx_graph.copy()))\n", + "morph_branch_nodes = [np.sort(b) for b in morph_branches]\n", + "\n", + "# do jx_trace after morph_traces, since jax_trace modifies the graph\n", + "jx_branches = _trace_branches(jx_graph.copy())[1]\n", + "jx_branch_nodes = [np.sort(np.unique(b[:, :-1])) for b in jx_branches]\n", + "# jx_branch_nodes = [b-1 for b in jx_branch_nodes]" + ] + }, + { + "cell_type": "code", + "execution_count": 860, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Get node positions and colors\n", + "pos = {node: (jx_graph.nodes[node]['x'], jx_graph.nodes[node]['y']) for node in jx_graph.nodes()}\n", + "\n", + "# Plot 1: Node indices\n", + "node_colors = [jx_graph.nodes[node]['id'] for node in jx_graph.nodes()]\n", + "nx.draw(jx_graph, pos=pos, node_color=node_colors, cmap='viridis', with_labels=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 856, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "([array([0., 1.]), array([1., 2., 3.]), array([1., 4., 5., 6.])],\n", + " [array([1, 2, 3]), array([1]), array([1, 4, 5, 6])])" + ] + }, + "execution_count": 856, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "jx_branch_nodes, morph_branch_nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 861, + "metadata": {}, + "outputs": [], + "source": [ + "morph_eq_jx = []\n", + "\n", + "for i, b in enumerate(jx_branch_nodes):\n", + " for j, mb in enumerate(morph_branch_nodes):\n", + " if len(b) == len(mb):\n", + " if np.allclose(b, mb):\n", + " morph_eq_jx.append((i,j))\n", + " break\n", + "if len(morph_eq_jx) > 0:\n", + " diff_morph_branches = [b for i, b in enumerate(morph_branch_nodes) if i not in np.array(morph_eq_jx)[:,1]]\n", + " diff_jx_branches = [b for j, b in enumerate(jx_branch_nodes) if j not in np.array(morph_eq_jx)[:,0]]\n", + "else:\n", + " print(\"No branches are equal\")\n", + " diff_morph_branches = morph_branch_nodes\n", + " diff_jx_branches = jx_branch_nodes" + ] + }, + { + "cell_type": "code", + "execution_count": 862, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABdEAAAHqCAYAAADrpwd3AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAL71JREFUeJzt3Xm4VXWh//HPOQdldgRBRRnVFAduerVfSoSzOFznoetAQmrmLJZDgaBp3UwUzHAo09JKc8gsRExuToV6HUNSsATlOiE5oQLnnP37g8uJA3zhqCACr9fz8Dyetdf+7u/mefC79nuvs1ZVpVKpBAAAAAAAWEj18p4AAAAAAAB8VonoAAAAAABQIKIDAAAAAECBiA4AAAAAAAUiOgAAAAAAFIjoAAAAAABQIKIDAAAAAECBiA4AAAAAAAUiOgAAAAAAFIjo8BnQpUuX9O/ff3lPY7HOP//8VFVVNdq2IswbAJirqqoqJ5100vKeBgB86vr37582bdos72ksN126dMk+++yzvKcBKzQRHRbws5/9LFVVVWnRokWmTZu20ONf/vKXs+WWWy6HmTXdijBHAFiW5q3njz32WCqVSnr37p327dvnzTffXGjfE044IauttlqefPLJxY7ZpUuXVFVVNfxp0aJFNtlkk5x11lmZMWPGMnonAPDZNW+9raqqyoMPPrjQ45VKJRtttFGqqqpW6Ij75S9/udExwOqrr56uXbvmuOOOy0svvbS8pwd8Cpot7wnAZ9WsWbPyve99LyNHjlzeU/nMeu6551Jd7bs4AD7bqqqqctVVV6VXr14ZNGhQrrvuuobH/vznP+fqq6/OGWeckV69ei1xrF69euXMM89Mknz44Yf5n//5n1x22WX505/+lEceeWRZvQUA+Exr0aJFbrrppuy0006Ntv/pT3/Kyy+/nObNmy+nmS09nTp1ysUXX5wkmT17dp599tmMGjUqY8aMycSJE9OqVavlPENgWRLRoaBXr1655pprcs4552SDDTZY3tP5TFoZDoQAWDVsscUWOeuss3LRRRelf//+6dOnT+bMmZPjjjsuG220UYYOHdqkcTbccMMceeSRDT8PHDgwbdq0ySWXXJJJkyZlk002KT535syZad269Sd+LwDwWdOvX7/ccsstGTFiRJo1+1dquummm7Lttttm+vTpS+216uvrM3v27LRo0WKpjdkUa665ZqNjgCTp2rVrTjrppDz00EPZbbfdis91DAArPqeQQsG5556burq6fO9731vivrW1tbngggvSvXv3NG/ePF26dMm5556bWbNmNdqvUqnkwgsvTKdOndKqVav07ds3EyZMWOSYb731Vk477bRstNFGad68eXr06JHvf//7qa+v/1jvZ951UO+4445sueWWad68eXr27Jm77757oX0ffPDB/Pu//3tatGiR7t2756qrrlrkmIu6Jvpbb72V008/PV26dEnz5s3TqVOnHH300Y0OmmbNmpUhQ4akR48ead68eTbaaKN885vfXOjva+zYsdlpp52y1lprpU2bNtlss81y7rnnfqz3DwDf+c530r179xx//PGZPXt2fvjDH+avf/1rrrjiik/0wbZjx45J0igazLv26gsvvJB+/fqlbdu2+c///M8kyQMPPJBDDjkkG2+8ccM6ePrpp+eDDz5oNO68MaZNm5b9998/bdq0Sfv27TNo0KDU1dU12re+vj6XX355ttpqq7Ro0SLt27fPnnvumccee2yh+TblWGDatGk59thj06FDh4b9fvrTny6038iRI9OzZ8+0atUqa6+9drbbbrvcdNNNH/0vEYAV2hFHHJE333wzY8eObdg2e/bs/OY3v8lXvvKVRT5n5syZOfPMMxs+82622Wa55JJLUqlUGu0377PsjTfemJ49e6Z58+a5++678+KLL6aqqiqXXHJJhg8fns6dO6dly5bp06dP/vrXvy7yNZuypn4UizoGmHc/sWeffTZf+cpXsvbaazecof/000+nf//+6datW1q0aJGOHTvm2GOPXehyc/PGmDx5cvr375+11lora665Zr761a/m/fffX2gev/jFL7L99ts3rMdf+tKXcs899yy034MPPpjtt98+LVq0SLdu3XLDDTcstE9TW8SvfvWrbLvttmnbtm3WWGONbLXVVrn88ss/+l8irCCciQ4FXbt2zdFHH51rrrkmZ5999mLPRh84cGCuv/76HHzwwTnzzDMzfvz4XHzxxZk4cWJuv/32hv0GDx6cCy+8MP369Uu/fv3y+OOPZ/fdd8/s2bMbjff++++nT58+mTZtWo4//vhsvPHGefjhh3POOefklVdeyWWXXfax3tODDz6Y2267LSeeeGLatm2bESNG5KCDDsrUqVOz7rrrJkmeeeaZ7L777mnfvn3OP//81NbWZsiQIenQocMSx3/vvffSu3fvTJw4Mccee2w+//nPZ/r06bnzzjvz8ssvp127dqmvr89+++2XBx98MMcdd1w233zzPPPMMxk+fHief/753HHHHUmSCRMmZJ999snWW2+dYcOGpXnz5pk8eXIeeuihj/XeAaBFixa58sors8cee+TEE0/MTTfdlAMOOCD77rtvk8eYM2dOwxfDH374YZ544olceuml+dKXvpSuXbs22re2tjZ77LFHdtppp1xyySUNv+Z9yy235P3338/Xv/71rLvuunnkkUcycuTIvPzyy7nlllsajVFXV5c99tgjO+ywQy655JLce++9+eEPf5ju3bvn61//esN+AwYMyM9+9rPstddeGThwYGpra/PAAw/kL3/5S7bbbruG/ZpyLPDaa6/lC1/4QkO0aN++fUaPHp0BAwbknXfeyWmnnZYkueaaa3LKKafk4IMPzqmnnpoPP/wwTz/9dMaPH18MJgCsnLp06ZL/9//+X375y19mr732SpKMHj06b7/9dg4//PCMGDGi0f6VSiX77bdfxo0blwEDBqRXr14ZM2ZMzjrrrEybNi3Dhw9vtP99992Xm2++OSeddFLatWuXLl26NDx2ww035N133803vvGNfPjhh7n88suz884755lnnmn0Obapa2pJXV1dwzHAnDlzMnHixIaTw3bccceF9j/kkEOyySab5KKLLmr4YmDs2LH5+9//nq9+9avp2LFjJkyYkKuvvjoTJkzIX/7yl1RVVTUa49BDD03Xrl1z8cUX5/HHH8+1116b9dZbL9///vcb9hk6dGjOP//8fPGLX8ywYcOy+uqrZ/z48bnvvvuy++67N+w3efLkHHzwwRkwYECOOeaY/PSnP03//v2z7bbbpmfPnkma3iLGjh2bI444IrvsskvDXCZOnJiHHnoop5566hL/LmGFVAEaue666ypJKo8++mjlhRdeqDRr1qxyyimnNDzep0+fSs+ePRt+fvLJJytJKgMHDmw0zqBBgypJKvfdd1+lUqlUXn/99crqq69e2XvvvSv19fUN+5177rmVJJVjjjmmYdsFF1xQad26deX5559vNObZZ59dqampqUydOnWx72HBOVYqlUqSyuqrr16ZPHlyw7annnqqkqQycuTIhm37779/pUWLFpUpU6Y0bHv22WcrNTU1lQX/l9G5c+dG8x48eHAlSeW2225baE7z3vPPf/7zSnV1deWBBx5o9PioUaMqSSoPPfRQpVKpVIYPH15JUnnjjTcW+14BYFHmX88XdMQRR1SSVNq2bVt56aWXmjxm586dK0kW+rPjjjtWpk+f3mjfY445ppKkcvbZZy80zvvvv7/QtosvvrhSVVXVaP2dN8awYcMa7ftv//ZvlW233bbh5/vuu6+SpNHxyjzzH3M09VhgwIABlfXXX3+h93T44YdX1lxzzYb5/8d//MdCxxsArFrmX2+vuOKKStu2bRvWiUMOOaTSt2/fSqUydw3de++9G553xx13VJJULrzwwkbjHXzwwZWqqqpGa1WSSnV1dWXChAmN9v3HP/5RSVJp2bJl5eWXX27YPn78+EqSyumnn96wralrakmfPn0WeQyw+eabV/7+97832nfIkCGVJJUjjjhioXEWdQzwy1/+spKkcv/99y80xrHHHtto3wMOOKCy7rrrNvw8adKkSnV1deWAAw6o1NXVNdp3/mOAeccw87/G66+/XmnevHnlzDPPbNjW1BZx6qmnVtZYY41KbW3twn9ZsJJyORdYjG7duuWoo47K1VdfnVdeeWWR+/zhD39IkpxxxhmNts+76djvf//7JMm9996b2bNn5+STT2707fK8s7nmd8stt6R3795Ze+21M3369IY/u+66a+rq6nL//fd/rPez6667pnv37g0/b7311lljjTXy97//Pcncb9bHjBmT/fffPxtvvHHDfptvvnn22GOPJY5/6623ZptttskBBxyw0GPz3vMtt9ySzTffPJ/73Ocavbedd945STJu3LgkyVprrZUk+e1vf/uxL2EDAIvSrl27JHOvk96pU6eP9NwddtghY8eOzdixY3PXXXflu9/9biZMmJD99ttvocuxJFnkmW0tW7Zs+O+ZM2dm+vTp+eIXv5hKpZInnnhiof1POOGERj/37t27Ye1O5q6/VVVVGTJkyELPXfCMtiUdC1Qqldx6663Zd999U6lUGq3Ve+yxR95+++08/vjjSeau1S+//HIeffTRRf5dAbBqOfTQQ/PBBx/krrvuyrvvvpu77rqr+JtJf/jDH1JTU5NTTjml0fYzzzwzlUolo0ePbrS9T58+2WKLLRY51v77758NN9yw4eftt98+O+ywQ8Nn9fktaU1dnC5dujQcA4wePTqXXXZZ3n777ey111554403lvhaSeNjgA8//DDTp0/PF77whSRpWF+XNN8333wz77zzTpK5l2irr6/P4MGDU13dOPEteAywxRZbpHfv3g0/t2/fPptttlmj99/UFrHWWmtl5syZjS7fAys7ER2W4Nvf/nZqa2uL10afMmVKqqur06NHj0bbO3bsmLXWWitTpkxp2C/JQjcca9++fdZee+1G2yZNmpS777477du3b/Rn1113TZK8/vrrH+u9zB/G51l77bXzz3/+M0nyxhtv5IMPPljkTdE222yzJY7/wgsvZMstt1zsPpMmTcqECRMWem+bbrppkn+9t8MOOyw77rhjBg4cmA4dOuTwww/PzTffLKgD8Ik89thj+dGPfpQtt9wy48ePzy9+8YuP9Px27dpl1113za677pq999475557bq699to8/PDDufbaaxvt26xZs0VG+qlTp6Z///5ZZ511Gq7J2qdPnyTJ22+/3Wjfedc3n9/8a3cyd/3dYIMNss466yxx/k05Fnjrrbdy9dVXL7RWf/WrX03yr7X6W9/6Vtq0aZPtt98+m2yySb7xjW+47BrAKmzeZ9abbropt912W+rq6nLwwQcvct8pU6Zkgw02SNu2bRtt33zzzRsen9+Cl0yb36I+v2666aZ58cUXG21rypq6OK1bt244Bthzzz1z6qmn5s4778xzzz23yF6wqDnPmDEjp556ajp06JCWLVumffv2DfsteAyQLLxuz2sH8+b8wgsvpLq6uvgFw+LGmjfe/O+/qS3ixBNPzKabbpq99tornTp1yrHHHrvIe6zAysQ10WEJunXrliOPPDJXX311zj777OJ+C37L+0nU19dnt912yze/+c1FPj4vOH9UNTU1i9xeWeDGLctSfX19ttpqq1x66aWLfHyjjTZKMvcb+vvvvz/jxo3L73//+9x999359a9/nZ133jn33HNP8b0AQEldXV2OO+64bLDBBnnooYey++6758wzz8w+++zT8BtQH8cuu+ySJLn//vtz8sknN2xv3rz5QmeF1dXVZbfddsuMGTPyrW99K5/73OfSunXrTJs2Lf3791/oy+Klvd4t6Vhg3usfeeSROeaYYxa579Zbb51kbuh47rnnctddd+Xuu+/OrbfemiuvvDKDBw/O0KFDl+q8AVgxfOUrX8nXvva1vPrqq9lrr70+0fo6v/nP4P64lsVnyG233TZrrrnmIn9bfFFzPvTQQ/Pwww/nrLPOSq9evdKmTZvU19dnzz33XOQJY0vzM3xTxmpqi1hvvfXy5JNPZsyYMRk9enRGjx6d6667LkcffXSuv/76jzw3WBGI6NAE3/72t/OLX/yi0c075uncuXPq6+szadKkhm/Nk7k35XrrrbfSuXPnhv2Sud/sduvWrWG/N954Y6Fvvrt375733nuv4dveT0v79u3TsmXLTJo0aaHHnnvuuSU+v3v37sW7oM+/z1NPPZVddtlliV88VFdXZ5dddskuu+ySSy+9NBdddFHOO++8jBs37lP/uwFgxTdixIg88cQTuf3227PGGmtk1KhR2W677XL22Wdn1KhRH3vc2traJHNvsL0kzzzzTJ5//vlcf/31Ofrooxu2f5Jfh+7evXvGjBmTGTNmNOls9MVp37592rZtm7q6uiatta1bt85hhx2Www47LLNnz86BBx6Y7373uznnnHPSokWLTzQXAFY8BxxwQI4//vj85S9/ya9//evifp07d869996bd999t9HZ6H/7298aHm+qRX1+ff755xvdfHRZqqura9IxwD//+c/88Y9/zNChQzN48OCG7Yuaf1N179499fX1efbZZ9OrV6+PPc784zW1Ray++urZd999s++++6a+vj4nnnhirrrqqnznO99Z6Df1YWXgci7QBN27d8+RRx6Zq666Kq+++mqjx/r165ckDXepnmfemdZ77713krnXIF1ttdUycuTIRt/0Lvi8ZO6303/+858zZsyYhR576623Gj6sL201NTXZY489cscdd2Tq1KkN2ydOnLjIuSzooIMOylNPPZXbb799ocfmvedDDz0006ZNyzXXXLPQPh988EFmzpyZZO6vuS1o3kHBrFmzmvR+AGCel156KYMHD85+++2X/fffP8ncdeWUU07JNddck/Hjx3/ssX/3u98lSbbZZpsl7jvvLLD5jwUqlUouv/zyj/36Bx10UCqVyiLP/v6oZ6rV1NTkoIMOyq233rrIL8bnv+brm2++2eix1VdfPVtssUUqlUrmzJnzkV4XgJVDmzZt8uMf/zjnn39+9t133+J+/fr1S11dXa644opG24cPH56qqqrstddeTX7NO+64I9OmTWv4+ZFHHsn48eM/0hgf17hx4/Lee+997GOAZNFNoKn233//VFdXZ9iwYQudyf5xzlZvaotY8Bigurq64TfVfF5nZeVMdGii8847Lz//+c/z3HPPpWfPng3bt9lmmxxzzDG5+uqr89Zbb6VPnz555JFHcv3112f//fdP3759k8w9s2vQoEG5+OKLs88++6Rfv3554oknMnr06IYbnM1z1lln5c4778w+++yT/v37Z9ttt83MmTPzzDPP5De/+U1efPHFhZ6ztAwdOjR33313evfunRNPPDG1tbUZOXJkevbsmaeffnqxzz3rrLPym9/8JoccckiOPfbYbLvttpkxY0buvPPOjBo1Kttss02OOuqo3HzzzTnhhBMybty47Ljjjqmrq8vf/va33HzzzRkzZky22267DBs2LPfff3/23nvvdO7cOa+//nquvPLKdOrUKTvttNMyee8ArLxOPvnkVCqVjBw5stH2oUOHNqxLjz322BJ/1XvatGkN11GfPXt2nnrqqVx11VVp165do0u5lHzuc59L9+7dM2jQoEybNi1rrLFGbr311iZfj3VR+vbtm6OOOiojRozIpEmTGn4l/IEHHkjfvn1z0kknfaTxvve972XcuHHZYYcd8rWvfS1bbLFFZsyYkccffzz33ntvwxfdu+++ezp27Jgdd9wxHTp0yMSJE3PFFVdk7733XugatwCsOkqXA5vfvvvum759++a8887Liy++mG222Sb33HNPfvvb3+a0005rdBPsJenRo0d22mmnfP3rX8+sWbNy2WWXZd111y1ekuTjevvttxuOAWpra/Pcc8/lxz/+cVq2bLnYS7/Os8Yaa+RLX/pS/uu//itz5szJhhtumHvuuSf/+Mc/PvacevTokfPOOy8XXHBBevfunQMPPDDNmzfPo48+mg022CAXX3zxRxqvqS1i4MCBmTFjRnbeeed06tQpU6ZMyciRI9OrV69Gv6EPKxMRHZqoR48eOfLIIxd5fa9rr7023bp1y89+9rPcfvvt6dixY84555wMGTKk0X4XXnhhWrRokVGjRjV8OL3nnnsazlafp1WrVvnTn/6Uiy66KLfccktuuOGGrLHGGtl0000zdOjQrLnmmsvsfW699dYZM2ZMzjjjjAwePDidOnXK0KFD88orrywxordp0yYPPPBAhgwZkttvvz3XX3991ltvveyyyy4NN1arrq7OHXfckeHDh+eGG27I7bffnlatWqVbt2459dRTG66xtt9+++XFF1/MT3/600yfPj3t2rVLnz59lvn7B2DlMO/sq5qamtxxxx357W9/m0suuWShm2q1bds2l19+eQ4++OCMGDEip59++mLHffLJJ3PUUUclmbumtWvXLgceeGAuuOCCbLjhhkuc12qrrZbf/e53OeWUU3LxxRenRYsWOeCAA3LSSSc16Sy2kuuuuy5bb711fvKTn+Sss87Kmmuume222y5f/OIXP/JYHTp0yCOPPJJhw4bltttuy5VXXpl11103PXv2bHRpu+OPPz433nhjLr300rz33nvp1KlTTjnllHz729/+2O8DgFVDdXV17rzzzgwePDi//vWvc91116VLly75wQ9+kDPPPPMjjXX00Uenuro6l112WV5//fVsv/32ueKKK7L++usv1Tm//PLLDccAVVVVWXvttdOnT58MGTKkyZdSuemmm3LyySfnRz/6USqVSnbfffeMHj06G2ywwcee17Bhw9K1a9eMHDky5513Xlq1apWtt966Ya4fRVNbxLz7xl155ZV566230rFjxxx22GE5//zzF7ofDKwsqiqf5h0FAQDgUzBixIiceuqpmTx58kc6mw0AWDG8+OKL6dq1a37wgx9k0KBBy3s6wErO10MAAKx0Hn300bRu3foj3ZgMAABgUVzOBQCAlcatt96a//7v/86NN96YgQMHplkzh7sAAMAn41MFAAArjUGDBuXdd9/NgAEDMnz48OU9HQAAYCXgmugAAAAAAFDgmugAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQEGz5T0BYNn54L0PMm3yq5kzqzarNW+WDXt0TMs2LZf3tACAgpmzavPimzMzu7Y+qzerTpd1W6d1c4fsAPBZZe2GVYN/1bCSmfLsS7lr1NiMH/14Xvn7a0llvgerkvW7dcgOe30++5ywWzpvsdFymycAMNek197NjeOnZtzfXs/UGe8vuHRn43Vape/n1st/7rBxNunQdnlNEwD4P9ZuWPVUVSqVypJ3Az7rXvnHa7nshKvz+NinU92sOvW19cV95z3++d22zmmjjsv6XTt8ijMFAJLkpRnv59zbnskDk6enproqdfXlw/J5j/fu0S4XHbhVNlqn1ac4UwAgsXbDqkxEh5XAH679Y350yk9SV1uXusXE8wXVNKtOTbOafGPEgPQbuMsynCEAML9fPTI1Q+6ckNr6ymI/gC+oproqzaqrMnS/njl8+42X4QwBgPlZu2HVJqLDCu7G796an33nV594nP4XHJ7/PO+gpTAjAGBxrrhvUi655/lPPM6g3TfNSTtvshRmBAAsjrUbENFhBfaHa/+Y4ceNWuRjtZXaTMlzeScz8nZmpDZzskW2ywZVXYrjnXHNCdlrgDPSAWBZ+dUjU3P2bc8s8rH62R/knfG3ZdYrz2X2K8+n/sP3sm6/09Jmq12L433/oK1y2L87qw0AlhVrN5Ak1ct7AsDH88o/XsuPTvlJ8fE5mZV/ZGJm5t20zVpNGvOKk3+SV/7x2lKaIQAwv5dmvJ8hd04oPl7/wTt5++FfZs6bL2W19bo2aczBv52Ql2a8v7SmCADMx9oNzCOiwwrqshOuTl1tXfHx5mmR3tknO1X1yybZqklj1tXW5bITrl5aUwQA5nPubc+kdnE3IGu9Tjp94+fp9PXrsvaXj23SmLX1lZxbODsOAPhkrN3APCI6rICmPPtSHh/79GJvIlpdVZPmVS0+0rh1tfV5fOzTmTLx5U86RQBgPpNeezcPTJ6+2BuRVTVbLTVt1v5I49bVV/LA5OmZ/Pq7n3SKAMB8rN3A/ER0WAHdNWpsqpstm3++Nc2qc9eP71kmYwPAqurG8VNTU121TMauqa7KL/4ydZmMDQCrKms3MD8RHVZA40c/nvrFnIX+SdTV1ueRu59YJmMDwKpq3N9eX+yZbJ9EXX0l4557fZmMDQCrKms3MD8RHVYw77/7QV75+7K9+ef/vvBqPnjvg2X6GgCwqnhvVm2mLuMbiE198/3MnFW7TF8DAFYV1m5gQSI6rGD+94VXk2XzZfi/VJJpk19dxi8CAKuGKW/O/DSW7rz45sxl/CoAsGqwdgMLEtFhBTPnU/qm+tN6HQBY2c1eRpdgW16vAwArO2s3sCARHVYwqzVvtlK9DgCs7FZfRjcDX16vAwArO2s3sCD/WmEFs2GPjsmyuUH4v1T93+sAAJ9Yl3VbfxpLd7qs23oZvwoArBqs3cCCnGoKK5iWbVpm/W4d8soLS7656EuVyZmTOZmduTcJfSOv5MPK3P/eOD3SrGq1RT5vg+4d07JNy6U3aQBYhbVu3iwbr9MqU5pwg7J3/ud3qZ81M3XvzUiSfDD5kdS+Oz1Jssa2+6a6+aI/bG+8bqu09ltkALBUWLuBBfnXCiugHfb6fO4cNSb1S7h+2pQ8nw/zr0X/jUzLG5mWJFk/G6dZFo7oNc2qs/2e/7Z0JwwAq7i+n1svP//LlNTVL/42Ze88cnvq3nm94ef3n384ef7hJEmbnn0X+UG8proqfTdbb+lOGABWcdZuYH5VlUplWd9wGFjKpjz7UgZuecYyG//aCcPTefNOy2x8AFjVTHrt3ew2/P5lNv69Z3wpPdZru8zGB4BVjbUbmJ9rosMKqPMWG+Xzu22dmqV8E5KaZtX5/G5bC+gAsJRt0qFtevdol5rqpXuF1ZrqqvTu0c6HcABYyqzdwPxEdFhBnTbquNQ0q1mqY9Y0q8lpo45bqmMCAHNddOBWabaUP4g3q67KRQdutVTHBADmsnYD84josIJav2uHfGPEgKU65kkjB2T9rh2W6pgAwFwbrdMqQ/fruVTHHPYfPbPROq2W6pgAwFzWbmAeER1WYP0G7pL+Fxy+VMb66oVHZK8BuyyVsQCARTt8+40zaPdNl8pYZ+2xWQ77942XylgAwKJZu4HEjUVhpfCHa/+YH53yk9TV1qWutr7Jz6tpVp2aZjU5aeQAAR0APkW/emRqhtw5IbX1ldTVN/1wvKa6Ks2qqzLsP3r6EA4AnyJrN6zaRHRYSbzyj9dy2QlX5/GxT6emWfViY/q8xz+/29Y5bdRxLuECAMvBSzPez7m3PZMHJk9PTXXVYj+Qz3u8d492uejArfwaOAAsB9ZuWHWJ6LCSmfLsS7lr1Ng8cvcT+d8XXk3m/xdelWzQvWO23/Pfss/Xd0/nzTstt3kCAHNNeu3d3Dh+asY993qmvvn+gkt3Nl63Vfputl6O/MLG6bFe2+U1TQDg/1i7YdUjosNK7IP3Psi0ya9mzqzarNa8WTbs0TEt27Rc3tMCAApmzqrNi2/OzOza+qzerDpd1m2d1s2bLe9pAQAF1m5YNYjoAAAAAABQUL28JwAAAAAAAJ9VIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUPD/AWz2c1EBAQcIAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "jx_subgraph = jx_graph.subgraph(np.unique(np.hstack(diff_morph_branches)))\n", + "\n", + "# Get node positions and colors\n", + "pos = {node: (jx_subgraph.nodes[node]['x'], jx_subgraph.nodes[node]['y']) for node in jx_subgraph.nodes()}\n", + "\n", + "# Create figure with 1x3 subplots\n", + "fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n", + "\n", + "# Plot 1: Node indices\n", + "node_colors = [jx_subgraph.nodes[node]['id'] for node in jx_subgraph.nodes()]\n", + "nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='viridis', with_labels=True, ax=axes[0])\n", + "axes[0].set_title('Node Indices')\n", + "\n", + "# Plot 2: JX branches\n", + "node_colors = np.zeros(len(jx_subgraph.nodes()))\n", + "for i, branch in enumerate(diff_jx_branches):\n", + " node_colors[np.isin(list(jx_subgraph.nodes()), branch)] = i + 1\n", + "nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='tab10', with_labels=True, ax=axes[1])\n", + "axes[1].set_title('JX Branches')\n", + "\n", + "# Plot 3: Morph branches\n", + "node_colors = np.zeros(len(jx_subgraph.nodes()))\n", + "for i, branch in enumerate(diff_morph_branches):\n", + " node_colors[np.isin(list(jx_subgraph.nodes()), branch)] = i + 1\n", + "nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='tab10', with_labels=True, ax=axes[2])\n", + "axes[2].set_title('Morph Branches')\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 661, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Morph branches:\n", + "\n", + "JX branches:\n" + ] + } + ], + "source": [ + "print(\"Morph branches:\")\n", + "for b in diff_morph_branches:\n", + " print([jx_graph.nodes[n][\"id\"] for n in b])\n", + "print()\n", + "print(\"JX branches:\")\n", + "for b in diff_jx_branches:\n", + " print([jx_graph.nodes[n][\"id\"] for n in b])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [], + "source": [ + "# for i, b in enumerate(morph_branch_nodes):\n", + "# pos = [(morph_graph.nodes[n][\"x\"], morph_graph.nodes[n][\"y\"]) for n in b]\n", + "# plt.plot(*zip(*pos))\n", + "\n", + "# for i, b in enumerate(jx_branch_nodes):\n", + "# pos = [(jx_graph.nodes[n][\"x\"], jx_graph.nodes[n][\"y\"]) for n in b]\n", + "# plt.plot(*zip(*pos))\n", + "# plt.show()\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 2\n", + "2 2\n", + "2 2\n", + "2 2\n", + "2 2\n", + "2 2\n", + "2 2\n", + "2 2\n", + "2 2\n", + "2 2\n", + "2 2\n", + "3 2\n", + "3 3\n", + "3 3\n", + "3 3\n", + "3 3\n", + "3 3\n", + "3 3\n", + "3 3\n", + "3 3\n", + "3 3\n", + "3 3\n", + "3 3\n", + "3 3\n", + "3 3\n", + "4 3\n", + "4 4\n", + "4 4\n", + "4 4\n", + "4 4\n", + "4 4\n", + "4 4\n", + "4 5\n", + "5 5\n", + "5 5\n", + "5 5\n", + "5 5\n", + "5 5\n", + "5 5\n", + "6 6\n", + "6 6\n", + "6 6\n", + "6 6\n", + "6 6\n", + "6 7\n", + "7 7\n", + "7 7\n", + "7 7\n", + "7 7\n", + "7 7\n", + "7 7\n", + "7 7\n", + "8 8\n", + "8 8\n", + "8 8\n", + "9 9\n", + "9 9\n", + "9 9\n", + "9 9\n", + "9 9\n", + "9 9\n", + "9 10\n", + "10 10\n", + "10 10\n", + "10 10\n", + "10 11\n", + "11 11\n", + "11 11\n", + "11 11\n", + "11 11\n", + "11 12\n", + "12 12\n", + "12 12\n", + "12 12\n", + "12 12\n", + "12 12\n", + "12 13\n", + "13 13\n", + "13 14\n", + "14 14\n", + "14 14\n", + "14 14\n", + "14 14\n", + "14 14\n", + "14 14\n", + "14 14\n", + "14 15\n", + "15 15\n", + "15 15\n", + "15 15\n", + "15 15\n", + "15 15\n", + "15 16\n", + "16 16\n", + "16 17\n", + "17 17\n", + "17 18\n", + "18 18\n", + "18 18\n", + "18 20\n", + "20 20\n", + "20 20\n", + "20 20\n", + "20 20\n", + "20 21\n", + "21 21\n", + "21 22\n", + "22 22\n", + "22 22\n", + "22 23\n", + "23 23\n", + "23 23\n", + "23 23\n", + "23 24\n", + "24 24\n", + "24 24\n", + "24 25\n", + "25 25\n", + "25 25\n", + "25 26\n", + "26 26\n", + "26 27\n", + "26 27\n", + "27 27\n", + "27 28\n", + "27 28\n", + "28 29\n", + "28 30\n", + "29 30\n", + "30 31\n", + "30 32\n", + "31 33\n", + "32 33\n", + "33 34\n", + "33 36\n", + "36 36\n", + "36 38\n", + "38 40\n", + "40 41\n", + "41 41\n", + "41 47\n", + "47 47\n", + "47 51\n", + "51 51\n", + "51 52\n", + "52 53\n", + "53 56\n", + "56 56\n", + "56 56\n", + "56 57\n", + "57 62\n", + "62 65\n", + "65 67\n", + "67 139\n" + ] + } + ], + "source": [ + "for jx_l, morph_l in zip(sorted(jx_branch_lens), sorted(morph_branch_lens)):\n", + " print(jx_l, morph_l)" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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IiJiOibsgVGAERERCXTV1oHxzMDoNmoRERHxa9VmYH59lIB/RwT/rk5EREQaXrUeGM/DHHUJScxox44dWCwW1q9f7+tSRESkoVWfgVEPjIiIiJiCWz0w4ufKy8t9XYKIiPgb9cDIqejXrx8TJ05k0qRJNG/enLi4OF544QWKi4sZPXo0kZGRnHnmmXz44YeezyxfvpzevXsTEhJCQkICd999NxUVFTXOOWHCBCZNmkTLli0ZMGAAABaLhTlz5jBw4EDCwsI4/fTT+d///ndcTT/99BMXXXQR4eHhdO3alaysrIb/ByEiIo2rqgfGph4Y/2IYUF7c+C/DqHOpL7/8Mi1btmT16tVMnDiRW265hauvvprzzjuPdevWcckllzBy5EhKSkrYu3cvgwYNolevXnzzzTfMmTOHf/3rXzz00EPHnTM4OJgvvviCuXPnerZPnz6dYcOG8c0335CRkcHw4cPZvHlzjc/ec889/PnPf2b9+vWcddZZjBgxokZAEhGRJsCEPTAWw6jHb1kfKywsxOFwUFBQQFRUVI19paWlbN++nZSUFEJDQys3lhfDI4mNX+hf9kFwxEkf3q9fP1wuFytXrgTA5XLhcDgYOnQor7zyCgA5OTkkJCSQlZXFe++9x5tvvsnmzZuxWCr/oj377LNMnTqVgoICrFYr/fr1o7CwkHXr1tX4XhaLhZtvvpk5c+Z4tp177rn06NGDZ599lh07dpCSksI///lPxowZA8CmTZvo1KkTmzdvpkOHDsfVX+s/exER8X8vXAx7s2HEa1z4big7fynhzVvS6HlajFe/zYl+f9dVYMzAmMg555zj+bPNZqNFixZ06dLFsy0uLg6AvLw8Nm/eTFpamie8APTt25eioiL27Nnj2dazZ89av1daWtpx74+dgaleT0JCgud7i4hIE1J9ITuT9MAExtOog8IrZ0N88X3r+pGgoBrvLRZLjW1VYcV9dIrvZEREnPws0Inqqc/3FhERE6ixDkzlz3h/fxZSYAQYi6VOl3LMomPHjrz55psYhuEJF1988QWRkZG0adPmdz//1VdfccMNN9R437179warV0RE/FSNHpgyQLdRSwO69dZb2b17NxMnTuT777/nnXfe4f7772fKlClYT2Lqb8GCBfz73/9m69at3H///axevZoJEyY0QuUiIuJXamni1QyMNJjWrVvzwQcf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owBTzTPPPEPbtm0JDQ2lT58+rF692tclnZLMzEx69epFZGQksbGxDBkyhC1bttQ4prS0lPHjx9OiRQuaNWvGsGHDyM3N9VHF3vPoo49isViYNGmSZ1tTGuvevXu5/vrradGiBWFhYXTp0oW1a9d69huGwX333UdCQgJhYWGkp6ezbds2H1Zcdy6Xi+nTp5OSkkJYWBhnnHEGDz74YI1nqJh1nCtWrODyyy8nMTERi8XCwoULa+w/mXEdPHiQjIwMoqKiiI6OZsyYMRQVFTXiKH7ficbpdDqZOnUqXbp0ISIigsTERG644Qb27dtX4xxmGCf8/r/T6m6++WYsFgszZ86ssd0MYz2ZcW7evJkrrrgCh8NBREQEvXr1YteuXZ793vpZrABz1Ouvv86UKVO4//77WbduHV27dmXAgAHk5eX5urR6W758OePHj+err75iyZIlOJ1OLrnkEoqLiz3HTJ48mffee48FCxawfPly9u3bx9ChQ31Y9albs2YNzz33HOecc06N7U1lrIcOHaJv374EBQXx4YcfsmnTJv7+97/TvHlzzzGPPfYYs2bNYu7cuaxatYqIiAgGDBhAaWmpDyuvmxkzZjBnzhz+8Y9/sHnzZmbMmMFjjz3G7NmzPceYdZzFxcV07dqVZ555ptb9JzOujIwMNm7cyJIlS1i0aBErVqxg3LhxjTWEk3KicZaUlLBu3TqmT5/OunXreOutt9iyZQtXXHFFjePMME74/X+nVd5++22++uorEhMTj9tnhrH+3jh//PFHzj//fDp06MBnn33Gt99+y/Tp0wkNDfUc47WfxYYYhmEYvXv3NsaPH+9573K5jMTERCMzM9OHVXlXXl6eARjLly83DMMw8vPzjaCgIGPBggWeYzZv3mwARlZWlq/KPCWHDx822rVrZyxZssS48MILjdtvv90wjKY11qlTpxrnn3/+b+53u91GfHy88fjjj3u25efnGyEhIcarr77aGCV6xWWXXWbcdNNNNbYNHTrUyMjIMAyj6YwTMN5++23P+5MZ16ZNmwzAWLNmjeeYDz/80LBYLMbevXsbrfa6OHactVm9erUBGDt37jQMw5zjNIzfHuuePXuM1q1bGxs2bDBOO+0046mnnvLsM+NYaxvntddea1x//fW/+Rlv/izWDAxQXl5OdnY26enpnm1Wq5X09HSysrJ8WJl3FRQUABATEwNAdnY2Tqezxrg7dOhAcnKyacc9fvx4LrvsshpjgqY11nfffZfU1FSuvvpqYmNj6d69Oy+88IJn//bt28nJyakxVofDQZ8+fUw11vPOO4+lS5eydetWAL755hs+//xzBg4cCDSdcR7rZMaVlZVFdHQ0qampnmPS09OxWq2sWrWq0Wv2loKCAiwWC9HR0UDTGqfb7WbkyJHceeeddOrU6bj9TWGsbreb999/n7POOosBAwYQGxtLnz59alxm8ubPYgUY4MCBA7hcLuLi4mpsj4uLIycnx0dVeZfb7WbSpEn07duXzp07A5CTk0NwcLDnh0UVs477tddeY926dWRmZh63rymN9aeffmLOnDm0a9eOjz76iFtuuYXbbruNl19+GcAzHrP/fb777rsZPnw4HTp0ICgoiO7duzNp0iQyMjKApjPOY53MuHJycoiNja2x3263ExMTY9qxl5aWMnXqVEaMGOF58F9TGueMGTOw2+3cdtttte5vCmPNy8ujqKiIRx99lEsvvZSPP/6YK6+8kqFDh7J8+XLAuz+LTfk0aqm78ePHs2HDBj7//HNfl9Igdu/eze23386SJUtqXGttitxuN6mpqTzyyCMAdO/enQ0bNjB37lxGjRrl4+q854033mDevHnMnz+fTp06sX79eiZNmkRiYmKTGqdUNvRec801GIbBnDlzfF2O12VnZ/P000+zbt06LBaLr8tpMG63G4DBgwczefJkALp168aXX37J3LlzufDCC736/TQDA7Rs2RKbzXZcF3Rubi7x8fE+qsp7JkyYwKJFi/j0009p06aNZ3t8fDzl5eXk5+fXON6M487OziYvL48ePXpgt9ux2+0sX76cWbNmYbfbiYuLazJjTUhI4Oyzz66xrWPHjp4u/6rxmP3v85133umZhenSpQsjR45k8uTJnhm2pjLOY53MuOLj44+7waCiooKDBw+abuxV4WXnzp0sWbLEM/sCTWecK1euJC8vj+TkZM/Pp507d3LHHXfQtm1boGmMtWXLltjt9t/9+eStn8UKMEBwcDA9e/Zk6dKlnm1ut5ulS5eSlpbmw8pOjWEYTJgwgbfffptly5aRkpJSY3/Pnj0JCgqqMe4tW7awa9cu0427f//+fPfdd6xfv97zSk1NJSMjw/PnpjLWvn37Hnc7/NatWznttNMASElJIT4+vsZYCwsLWbVqlanGWlJSgtVa80eUzWbz/F9eUxnnsU5mXGlpaeTn55Odne05ZtmyZbjdbvr06dPoNddXVXjZtm0bn3zyCS1atKixv6mMc+TIkXz77bc1fj4lJiZy55138tFHHwFNY6zBwcH06tXrhD+fvPp7p04tv03Ya6+9ZoSEhBgvvfSSsWnTJmPcuHFGdHS0kZOT4+vS6u2WW24xHA6H8dlnnxk///yz51VSUuI55uabbzaSk5ONZcuWGWvXrjXS0tKMtLQ0H1btPdXvQjKMpjPW1atXG3a73Xj44YeNbdu2GfPmzTPCw8ON//73v55jHn30USM6Otp45513jG+//dYYPHiwkZKSYhw5csSHldfNqFGjjNatWxuLFi0ytm/fbrz11ltGy5YtjbvuustzjFnHefjwYePrr782vv76awMwnnzySePrr7/23H1zMuO69NJLje7duxurVq0yPv/8c6Ndu3bGiBEjfDWkWp1onOXl5cYVV1xhtGnTxli/fn2Nn1FlZWWec5hhnIbx+/9Oj3XsXUiGYY6x/t4433rrLSMoKMh4/vnnjW3bthmzZ882bDabsXLlSs85vPWzWAGmmtmzZxvJyclGcHCw0bt3b+Orr77ydUmnBKj19eKLL3qOOXLkiHHrrbcazZs3N8LDw40rr7zS+Pnnn31XtBcdG2Ca0ljfe+89o3PnzkZISIjRoUMH4/nnn6+x3+12G9OnTzfi4uKMkJAQo3///saWLVt8VG39FBYWGrfffruRnJxshIaGGqeffrpxzz331PjlZtZxfvrpp7X+tzlq1CjDME5uXL/88osxYsQIo1mzZkZUVJQxevRo4/Dhwz4YzW870Ti3b9/+mz+jPv30U885zDBOw/j9f6fHqi3AmGGsJzPOf/3rX8aZZ55phIaGGl27djUWLlxY4xze+llsMYxqy1qKiIiImIB6YERERMR0FGBERETEdBRgRERExHQUYERERMR0FGBERETEdBRgRERExHQUYERERMR0FGBERETEdBRgRERExHQUYERERMR0FGBERETEdBRgRERExHT+P8ayTRYnHRwBAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(np.sort(jx_branch_lens), label=\"jx\")\n", + "plt.plot(np.sort(morph_branch_lens), label=\"morph\")\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def infer_module_type_from_inds(idxs: pd.DataFrame) -> str:\n", + " nuniques = idxs[[\"cell_index\", \"branch_index\", \"comp_index\"]].nunique()\n", + " nuniques.index = [\"cell\", \"branch\", \"compartment\"]\n", + " nuniques = pd.concat([pd.Series({\"network\": 1}), nuniques])\n", + " return_type = nuniques.loc[nuniques == 1].index[-1]\n", + " return return_type\n", + "\n", + "\n", + "def build_module_scaffold(\n", + " idxs: pd.DataFrame,\n", + " return_type: Optional[str] = None,\n", + " parent_branches: Optional[List[np.ndarray]] = None,\n", + ") -> Union[jx.Network, jx.Cell, jx.Branch, jx.Compartment]:\n", + " \"\"\"Builds a skeleton module from a DataFrame of indices.\n", + " This is useful for instantiating a module that can be filled with data later.\n", + " Args:\n", + " idxs: DataFrame containing cell_index, branch_index, comp_index, i.e.\n", + " Module.nodes or View.view.\n", + " return_type: Type of module to return. If None, the type is inferred from the\n", + " number of unique values in the indices. I.e. only 1 unique cell_index\n", + " and 1 unique branch_index -> return_type = \"jx.Branch\".\n", + " Returns:\n", + " A skeleton module with the correct number of compartments, branches, cells, or\n", + " networks.\"\"\"\n", + " return_types = [\"compartment\", \"branch\", \"cell\", \"network\"]\n", + " build_cache = {k: [] for k in return_types}\n", + "\n", + " if return_type is None: # infer return type from idxs\n", + " return_type = infer_module_type_from_inds(idxs)\n", + "\n", + " comp = jx.Compartment()\n", + " build_cache[\"compartment\"] = [comp]\n", + "\n", + " if return_type in return_types[1:]:\n", + " nsegs = idxs[\"branch_index\"].value_counts().iloc[0]\n", + " branch = jx.Branch([comp for _ in range(nsegs)])\n", + " build_cache[\"branch\"] = [branch]\n", + "\n", + " if return_type in return_types[2:]:\n", + " for cell_id, cell_groups in idxs.groupby(\"cell_index\"):\n", + " num_branches = cell_groups[\"branch_index\"].nunique()\n", + " default_parents = np.arange(num_branches) - 1 # ignores morphology\n", + " parents = (\n", + " default_parents if parent_branches is None else parent_branches[cell_id]\n", + " )\n", + " cell = jx.Cell([branch] * num_branches, parents)\n", + " build_cache[\"cell\"].append(cell)\n", + "\n", + " if return_type in return_types[3:]:\n", + " build_cache[\"network\"] = [jx.Network(build_cache[\"cell\"])]\n", + "\n", + " module = build_cache[return_type][0]\n", + " build_cache.clear()\n", + " return module" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def convert_view_to_module(view: View, reset_index: bool = True) -> \"Module\":\n", + " \"\"\"Extract part of a module and return a copy of its View or a new module.\n", + "\n", + " This can be used to call `jx.integrate` on part of a Module.\n", + "\n", + " Args:\n", + " reset_index: if True, the indices of the new module are reset to start from 0.\n", + " as_module: if True, a new module is returned instead of a View.\n", + "\n", + " Returns:\n", + " A part of the module or a copied view of it.\"\"\"\n", + " view = deepcopy(view)\n", + " if reset_index:\n", + " view.nodes.reset_index(drop=True, inplace=True)\n", + " view.edges.reset_index(drop=True, inplace=True)\n", + " # TODO: also re-enumerate cell,branch,comp indices in nodes and edges\n", + "\n", + " testnodes = view.nodes.copy()\n", + " testnodes.rename({\"global_\"+k:k for k in [\"cell_index\", \"branch_index\", \"comp_index\"]}, axis=1, inplace=True)\n", + " mod_type = infer_module_type_from_inds(testnodes)\n", + " module = build_module_scaffold(testnodes, mod_type)\n", + " module.__dict__.update(view.__dict__)\n", + " return module" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Added 2 recordings. See `.recordings` for details.\n" + ] + }, + { + "data": { + "text/plain": [ + "Array([[-70. , -69.48756081, -69.09088174, -68.77443768,\n", + " -68.51477492, -68.29603413, -68.10727942, -67.94084395,\n", + " -67.79127429, -67.65464046, -67.52807603, -67.40946647,\n", + " -67.29723486, -67.19019277, -67.0874353 , -66.98826644,\n", + " -66.89214546, -66.7986481 , -66.70743824, -66.61824695,\n", + " -66.53085703, -66.44509138, -66.36080422, -66.27787448,\n", + " -66.19620072, -66.11569714, -66.03629063, -65.9579183 ,\n", + " -65.8805257 , -65.80406526, -65.72849517, -65.6537784 ,\n", + " -65.57988194, -65.50677619, -65.43443445, -65.3628325 ,\n", + " -65.29194826, -65.22176147, -65.15225352, -65.08340718,\n", + " -65.01520646]], dtype=float64)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "branch = jx.Branch(ncomp=2)\n", + "branch[0].insert(HH())\n", + "branch.record()\n", + "\n", + "comp = branch[0]\n", + "comp = convert_view_to_module(comp)\n", + "jx.integrate(comp, t_max=1)" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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lx1wE8y78lR3dzduPuZf6C4xek2OsJeHcg6P4dvfHHlVl7qdFzZnqLijzr/32g1/1P10wutwV6VnaB++MeKN4R6Ls27bSfOvLUw/eZMmTQoODrZarQcOHPj663ObqK5atWr69OnLli1zOp0ZGRn1kqZL2bVrV8+ePceMGVNRUbFgwQL/qY6lpaVffPHF1KlT1Wr15s2bly9fTkQ//fSTUCi8//77n3jiCaPRmJ2dXVFR4bvl6NGjNTU1N9988549e/x7EQqFAwYMWLRoUcMB8PtF+rahbAtNPGNDZWVly5YtmzFjhkAgqKqq2rRp0/jx4/kqu93es2fP++67TyKRFBcXL1iwgD/uZvv27R07dkxLS/N6vSdPnty2bVszp7g2auHChY8//viwYcOsVuv69evrpZA7duy48847MzIyGt74888/p6amrl271r9w3rx5arWaiOLj4/v27ZuVlTVv3rwmet+5c2dgYOCECRMUCsWxY8c+/vhj/9rY2NiwsLDdu3c3vPG2227bvn17w0gaAAAAAAAAANoOExsbe73H0OYCbu+iHBhX9uaW6z2Q64ARCsLmDjes+c129NxRLaqh3RR9O/J561/Vyy+/XFZWxmeRrWXQoEHDhw+fPXu2f2FKSsrQoUPnzJnT8PqnnnoqLi7uhRde4BdiN9MXX3yRnp7uW4vdhLZ4xuuoX79+Tz/99NSpU+vtFUBEQqHw/fffX7FiRaOzIFvF008/bTAYVq9eXa88LCxswYIFzz77LPayBAAAAAAAALiWrs8syysVPWB81/vnNlr1y5yunMfdaBUJGaFSwohF8ltiHVexI+SfGufx6j/fL9LJr/dA/vR27dql1WpVKpX/IS0MwyxZsqTR6xMTE5cvX97MvFKpVIpEol69esnl8r/btolisTgwMHDUqFEZGRkN80oi8ng86enpQUFBbTQAgUBQVlb244+NhPg6nS49PR15JQAAAAAAAMA19ueILIv3ri7eW38C1GVJOgaFvngHeTjH6SrjpqNtMbA/BWdBtfPvFYK1CY7jvv/++3qF9Y639jdt2rTmN/7888/37NnTaDR+9tlnbbqWvB269957R48effz4cd9WAA3l5OTk5OS00QC8Xu/69esbrTp+/HgbdQoAAAAAAAAATfhbLAxvVzQP9Wm03PZb8WX3lAQAAAAAAAAAAPjLQ2QJAAAA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" + } + }, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- change param / state naming convenetion for channels and synapses\n", + "- ensure that channel/synapse currents are prefixed on the module side\n", + "- ensure that args and kwargs in channels functions are same order and standardized (enforce this with tests)\n", + "- make channel / synapse name user facing ?\n", + "- jx.integrate(net1, t_max=0) runs one step\n", + "- are we testing inner vs outer loop of setting states / params in init_states / _step_channel_currents etc?\n", + "- add test to see if indices are handled correctly for two different mechs changing the same state at non-overlapping indices\n", + "- fix: ![image.png](attachment:image.png)\n", + "- add prepare_mechansim function (assert name does not exist already, assert conform to build rules)\n", + "- warn if states / params does not contain all global params\n", + "update_states vs. init_state\n", + "try:\n", + " channel.update_states()\n", + " channel.compute_current()\n", + " channel.init_states()\n", + "except KeyError:\n", + " warn(\"Some global param / state seems to be misssing\")\n", + "\n", + "\n", + "- in the new channel API, `_filter_params_states` would have to filter potentially all channels, even the ones not in the channel. Better Solution! only filter global states!\n", + "- add current_name to synapses\n", + "- store global parameters in jaxnodes only once! i.e. for any global param jaxnodes[\"global_param_name\"].shape == (1,) and duplicate if it is used multiple times\n", + "- should compute_current get dt arg?" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "def get_params_all_trainable(net):\n", + " net.cell(\"all\").branch(\"all\").loc(\"all\").make_trainable(\"HH_gNa\")\n", + " params = net.get_parameters()\n", + " params[0][\"HH_gNa\"] = params[0][\"HH_gNa\"].at[:].set(0.0)\n", + " net.to_jax()\n", + " pstate = params_to_pstate(params, net.indices_set_by_trainables)\n", + " print(pstate)\n", + " return net.get_all_parameters(pstate, voltage_solver=\"jaxley.thomas\")\n", + "\n", + "def get_params_set(net):\n", + " net.set(\"HH_gNa\", 0.0)\n", + " params = net.get_parameters()\n", + " net.to_jax()\n", + " pstate = params_to_pstate(params, net.indices_set_by_trainables)\n", + " return net.get_all_parameters(pstate, voltage_solver=\"jaxley.thomas\")\n", + "\n", + "def SimpleComp():\n", + " comp = jx.Compartment()\n", + " return comp\n", + "\n", + "def SimpleBranch(ncomp):\n", + " comp = jx.Compartment()\n", + " branch = jx.Branch([comp]*ncomp)\n", + " return branch\n", + "\n", + "def SimpleCell(nbranch, ncomp):\n", + " branch = SimpleBranch(ncomp)\n", + " cell = jx.Cell([branch]*nbranch, parents=[-1, 0, 0, 1, 1, 2, 2, 3, 3][:nbranch])\n", + " return cell\n", + "\n", + "def SimpleNet(ncell, nbranch, ncomp):\n", + " cell = SimpleCell(nbranch, ncomp)\n", + " net = jx.Network([cell]*ncell)\n", + " return net" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 189, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of newly added trainable parameters: 3. Total number of trainable parameters: 3\n" + ] + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 222, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 223, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Array([[ 1, 2, -1],\n", + " [ 6, 7, -1],\n", + " [ 3, -1, -1]], dtype=int64)" + ] + }, + "execution_count": 223, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# global_params = [\"v\", \"radius\", \"length\", \"axial_resistivity\", \"capacitance\"]\n", + "# jaxnodes = {\"global\": {param: jnp.asarray(cell.nodes[param]) for param in global_params}}\n", + "\n", + "# # Add channel-specific nodes and update globals\n", + "# for channel in cell.channels:\n", + "# channel_dict = {}\n", + "# for param, value in {**channel.states, **channel.params}.items():\n", + "# if f\"{channel._name}_\" in param:\n", + "# channel_dict[param] = jnp.asarray(cell.nodes[param][channel.indices])\n", + "# else:\n", + "# jaxnodes[\"global\"][param] = jnp.asarray(cell.nodes[param])\n", + "# jaxnodes[channel._name] = channel_dict\n", + "\n", + "# # Update channel states\n", + "# for channel in cell.channels:\n", + "# # Combine channel-specific and global nodes\n", + "# channel_nodes = jaxnodes[channel._name].copy()\n", + "# channel_nodes.update({k: v[channel.indices] for k, v in jaxnodes[\"global\"].items()})\n", + " \n", + "# # Update states\n", + "# channel_states_updated = channel.update_states(\n", + "# channel_nodes, 0.025, channel_nodes[\"v\"], channel_nodes\n", + "# )\n", + " \n", + "# # Apply updates back to jaxnodes\n", + "# for key, val in channel_states_updated.items():\n", + "# mech_key = \"global\" if key in jaxnodes[\"global\"] else channel._name\n", + "# jaxnodes[mech_key][key] = jaxnodes[mech_key][key].at[channel.indices].set(val)\n", + "\n", + "# def _iter_states_params(self, params=False, states=False) -> Tuple[str, jnp.ndarray]:\n", + "# # TODO FROM #447: MAKE THIS WORK FOR VIEW?\n", + "\n", + "# # assert that either params or states is True\n", + "# assert params or states, \"Either params or states must be True.\"\n", + "# global_states = [\"v\"]\n", + "# morph_params = [\"radius\", \"length\", \"axial_resistivity\", \"capacitance\"]\n", + "\n", + "# for key in global_states + morph_params:\n", + "# yield \"global\", key, self._inds_of_state_param[key]\n", + " \n", + "# mechs = self.channels + self.synapses\n", + "# for mech in mechs:\n", + "# data = self.nodes if isinstance(mech, Channel) else self.edges\n", + "# params_states = mech.params if params else []\n", + "# params_states += mech.states if states else []\n", + "# for key in params_states:\n", + "# if f\"{mech._name}_\" not in key:\n", + "# yield \"global\", key, jnp.asarray(data.index)\n", + "# else:\n", + "# yield mech._name, key, mech.indices\n", + "\n", + "# def _get_all_states_params(\n", + "# self,\n", + "# pstate: List[Dict],\n", + "# voltage_solver=None,\n", + "# delta_t=None,\n", + "# all_params=None,\n", + "# params=False,\n", + "# states=False,\n", + "# ) -> Dict[str, jnp.ndarray]:\n", + "# states_params = {}\n", + "# pkeys = {k:[] for k in pstate}\n", + "# for i, p in enumerate(pstate):\n", + "# pkeys[p[\"key\"]] += [i]\n", + "\n", + "# for mech_key, key, _ in self._iter_states_params(params, states):\n", + "# jax_arrays = self.jaxnodes if key in self.nodes.columns else self.jaxedges\n", + "# states_params[mech_key][key] = jax_arrays[mech_key][key]\n", + "\n", + "# if key in pkeys:\n", + "# for i in pkeys[key]:\n", + "# # `inds` is of shape `(num_params, num_comps_per_param)`.\n", + "# # `set_param` is of shape `(num_params,)`\n", + "# # We need to unsqueeze `set_param` to make it `(num_params, 1)`\n", + "# # for the `.set()` to work. This is done with `[:, None]`.\n", + "# inds, set_param = pstate[i][\"indices\"], pstate[i][\"val\"]\n", + "# states_params[mech_key][key] = states_params[key].at[inds].set(set_param[:, None])\n", + "\n", + "# if params:\n", + "# # Compute conductance params and add them to the params dictionary.\n", + "# states_params[\"axial_conductances\"] = self._compute_axial_conductances(\n", + "# params=states_params\n", + "# )\n", + "\n", + "# if states:\n", + "# all_params = states_params if all_params is None and params else all_params\n", + "# for current in self.membrane_current_names:\n", + "# states_params[current] = jnp.zeros_like(states_params['v'])\n", + "# # Add to the states the initial current through every channel.\n", + "# states, _ = self._channel_currents(\n", + "# states_params, delta_t, self.channels, self.nodes, all_params\n", + "# )\n", + "\n", + "# # Add to the states the initial current through every synapse.\n", + "# states, _ = self._synapse_currents(\n", + "# states_params, self.synapses, all_params, delta_t, self.edges\n", + "# )\n", + "# return states_params\n", + " " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From feb4cecc8a2b2580b6eb12b1204cc37ae5ca8edb Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Fri, 23 May 2025 17:48:32 +0200 Subject: [PATCH 02/24] wip: save wip, compartmentalization seems to work much better now --- dev.ipynb | 635 +++++++++++++++++++++++------------------------------- 1 file changed, 274 insertions(+), 361 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index ab45c19b7..1032a411a 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 834, + "execution_count": 989, "metadata": {}, "outputs": [], "source": [ @@ -163,11 +163,7 @@ " # trace dir matters here! For segment with node IDs: [1, 1, 2, 2]\n", " # -> [[1,1], [1,2,2]] \n", " # <- [[2,2], [2,1,1]] \n", - " if is_soma(n):\n", - " return not same_id(n, j)\n", - " else:\n", - " # return not any([same_id(n, i), same_id(n, j)])\n", - " return not same_id(n, j)\n", + " return not same_id(n, j)\n", " \n", " return is_leaf or is_branching\n", "\n", @@ -200,9 +196,9 @@ " return path\n", "\n", " leaf = next(n for n in G.nodes if G.degree(n) == 1)\n", - " soma_nodes = soma_nodes()\n", + " single_soma = len(soma_nodes()) == 1\n", " for node in nx.dfs_tree(G, leaf):\n", - " if is_soma(node) and len(soma_nodes) == 1:\n", + " if single_soma and is_soma(node):\n", " branches.append([node])\n", "\n", " elif is_branchpoint(node):\n", @@ -216,64 +212,79 @@ " return branches, branchpoints, branchpoint_edges\n", " return branches\n", "\n", - "# def compartmentalize(tree: MorphTree, num_comps: int = 1) -> MorphTree:\n", - "# branches = list_branches(tree)\n", - "# nodes_df, _ = tree.to_pandas()\n", - "# nodes_df = nodes_df.astype(float)\n", + "def compartmentalize(tree: MorphTree, num_comps: int = 1) -> MorphTree:\n", + " branches = list_branches(tree)\n", + " nodes_df, _ = tree.to_pandas()\n", + " nodes_df = nodes_df.astype(float)\n", "\n", - "# new_inds = len(branches)*num_comps\n", - "# existing_inds = set(nodes_df.index)\n", - "# proposed_new_inds = set(range(len(branches)*num_comps + len(existing_inds)))\n", - "# new_inds = list(proposed_new_inds.difference(existing_inds))\n", + " new_inds = len(branches)*num_comps\n", + " existing_inds = set(nodes_df.index)\n", + " proposed_new_inds = set(range(len(branches)*num_comps + len(existing_inds)))\n", + " new_inds = list(proposed_new_inds.difference(existing_inds))\n", " \n", - "# branch_nodes: List[np.ndarray] = []\n", - "# branch_edges: List[List[Tuple[int, int]]] = []\n", - "# for i, b in enumerate(branches):\n", - "# branch_node_attrs = nodes_df.loc[b]\n", - "# xyz_i = branch_node_attrs[[\"x\", \"y\", \"z\"]]\n", - "# pathlen = ((xyz_i.diff(axis=0).fillna(0)**2).sum(axis=1)**.5)\n", - "# branch_node_attrs[\"l\"] = pathlen.cumsum()\n", - "# v_interp = vmap(jnp.interp, in_axes=(None, None, 1), out_axes=1)\n", - "\n", - "# branch_len = max(branch_node_attrs[\"l\"])\n", - "# comp_len = branch_len / num_comps\n", - "# comp_locs = jnp.linspace(comp_len/2, branch_len - comp_len/2, num_comps)\n", + " branch_nodes: List[np.ndarray] = []\n", + " branch_edges: List[List[Tuple[int, int]]] = []\n", + " for i, b in enumerate(branches):\n", + " branch_node_attrs = nodes_df.loc[b]\n", + " xyz_i = branch_node_attrs[[\"x\", \"y\", \"z\"]]\n", + " pathlen = ((xyz_i.diff(axis=0).fillna(0)**2).sum(axis=1)**.5)\n", + " branch_node_attrs[\"l\"] = pathlen.cumsum()\n", " \n", - "# x = jnp.array([0] + list(comp_locs) + [branch_len])\n", - "# xp = jnp.array(branch_node_attrs[\"l\"].values)\n", - "# fp = jnp.array(branch_node_attrs[[\"x\", \"y\", \"z\", \"r\"]].values)\n", - "\n", - "# tmp_inds = [b[0]] + new_inds[i:i+num_comps] + [b[-1]]\n", - "# types = [0] + [1]*num_comps + [0] # 0: branchpoint, 1: compartment\n", - "# branch_idx = [i]*(num_comps+2)\n", - "# comp_inds_and_type = np.array([tmp_inds, branch_idx, types]).T\n", - "# comp_xyzr = np.array(v_interp(x, xp, fp))\n", - "# comp_xyzr = np.hstack([comp_inds_and_type, comp_xyzr])\n", - "\n", - "# branch_edges.append([(i,j) for i,j in zip(tmp_inds[:-1], tmp_inds[1:])])\n", - "# branch_nodes.append(comp_xyzr)\n", - "\n", - "# branch_nodes = jnp.concatenate(branch_nodes)\n", - "# comp_attrs_keys = [\"idx\", \"branch\", \"type\", \"x\", \"y\", \"z\", \"r\"]\n", - "# comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", - "# comp_df[[\"idx\", \"branch\", \"type\"]] = comp_df[[\"idx\", \"branch\", \"type\"]].astype(int)\n", + " # For single-point somatata, we set l = 2*r this ensures\n", + " # A_cylinder = 2*pi*r*l = 4*pi*r^2 = A_sphere.\n", + " if len(b) == 1:\n", + " branch_node_attrs = branch_node_attrs.loc[b*2] # duplicate soma node\n", + " radius = branch_node_attrs[\"r\"].iloc[0]\n", + " branch_node_attrs[\"l\"] = np.array([0, 2*radius])\n", + "\n", + " v_interp = vmap(jnp.interp, in_axes=(None, None, 1), out_axes=1)\n", + "\n", + " branch_len = max(branch_node_attrs[\"l\"])\n", + " comp_len = branch_len / num_comps\n", + " comp_locs = jnp.linspace(comp_len/2, branch_len - comp_len/2, num_comps)\n", + " \n", + " x = jnp.array([0] + list(comp_locs) + [branch_len])\n", + " xp = jnp.array(branch_node_attrs[\"l\"].values)\n", + " fp = jnp.array(branch_node_attrs[[\"x\", \"y\", \"z\", \"r\"]].values)\n", + "\n", + " # Create node indices and attributes\n", + " node_attrs = np.array([\n", + " [b[0]] + new_inds[i:i+num_comps] + [b[-1]], # indices\n", + " [i]*(num_comps+2), # branch indices\n", + " [0] + [1]*num_comps + [0], # types (0=branchpoint, 1=compartment)\n", + " [-1] + [branch_node_attrs[\"id\"].iloc[-1]]*num_comps + [-1], # ids\n", + " [0] + [comp_len]*num_comps + [0] # lengths\n", + " ]).T\n", + " \n", + " # Interpolate xyzr coordinates and combine with attributes\n", + " comp_xyzr = np.hstack([node_attrs, np.array(v_interp(x, xp, fp))])\n", + " \n", + " # Store edges and nodes\n", + " branch_edges.append(list(zip(node_attrs[:-1, 0], node_attrs[1:, 0])))\n", + " branch_nodes.append(comp_xyzr)\n", + "\n", + " branch_nodes = jnp.concatenate(branch_nodes)\n", + " comp_attrs_keys = [\"idx\", \"branch\", \"type\", \"id\", \"x\", \"y\", \"z\", \"r\", \"l\"]\n", + " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", + " int_cols = [\"idx\", \"branch\", \"type\", \"id\"]\n", + " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", " \n", - "# # drop duplicated branch nodes\n", - "# comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", - "# comp_df = comp_df.set_index(\"idx\")\n", + " # drop duplicated branch nodes\n", + " comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", + " comp_df = comp_df.set_index(\"idx\")\n", "\n", - "# comps = jnp.array(comp_df.index)\n", - "# comp_attrs = comp_df.to_dict(orient=\"records\")\n", - "# comp_edges = jnp.array(sum(branch_edges, []))\n", + " comps = jnp.array(comp_df.index)\n", + " comp_attrs = comp_df.to_dict(orient=\"records\")\n", + " comp_edges = jnp.array(sum(branch_edges, []))\n", "\n", - "# comp_tree = MorphTree(comps, comp_edges, comp_attrs)\n", - "# comp_tree = comp_tree.reindex_nodes(jnp.arange(len(comps)))\n", - "# return comp_tree" + " comp_tree = MorphTree(comps, comp_edges, comp_attrs)\n", + " comp_tree = comp_tree.reindex_nodes(jnp.arange(len(comps)))\n", + " return comp_tree" ] }, { "cell_type": "code", - "execution_count": 835, + "execution_count": 990, "metadata": {}, "outputs": [], "source": [ @@ -304,11 +315,11 @@ }, { "cell_type": "code", - "execution_count": 859, + "execution_count": 991, "metadata": {}, "outputs": [], "source": [ - "from jaxley.io.graph import build_compartment_graph, to_swc_graph, _trace_branches\n", + "from jaxley.io.graph import build_compartment_graph, to_swc_graph, _trace_branches, _remove_branch_points\n", "\n", "testcases = [ \n", "\"morph_3_types_single_point_soma.swc\",\n", @@ -323,25 +334,20 @@ "\"morph_allen_485574832.swc\",\n", "]\n", "\n", - "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[9])\n", - "\n", - "morph_branches = list_branches(MorphTree.from_nx(jx_graph.copy()))\n", - "morph_branch_nodes = [np.sort(b) for b in morph_branches]\n", + "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[0])\n", "\n", - "# do jx_trace after morph_traces, since jax_trace modifies the graph\n", - "jx_branches = _trace_branches(jx_graph.copy())[1]\n", - "jx_branch_nodes = [np.sort(np.unique(b[:, :-1])) for b in jx_branches]\n", - "# jx_branch_nodes = [b-1 for b in jx_branch_nodes]" + "morph_comps = compartmentalize(MorphTree.from_nx(jx_graph.copy()), num_comps=1)\n", + "jx_comps = build_compartment_graph(jx_graph, ncomp=1)" ] }, { "cell_type": "code", - "execution_count": 860, + "execution_count": 899, "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/png": "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/HhwcLDi4+PVpk0bXXXVVRo+fDhTR/iEwsJCvfbaa1q0aJHS09O1f//+37wQFB4erhYtWmjo0KEaN24c/24DXoxCCXiRjIwMTZ48WZ9++qmys7NP+AJrt9sVHx+vrl276rbbblPfvn0NJgWqnmVZWrp0qaZPn65169Zp//79J0wyg4KCVL9+ffXp00d33XWX0tLSDKYF8EsUSsCg9957Ty+99JK+/vprHTx48ITnHp1Opxo1aqQBAwbo73//uxITEw0mBczIzs7WU089pSVLligrK+uERzxsNptiY2PVoUMH3XLLLRo8eLDBpEBgo1ACNWjNmjV65JFHtHbtWh05cuSEH6tVq5ZatWqlESNG6M9//jNvWQO/w+VyaebMmZo9e7Z++OEHHT58+IQfj4qKUufOnTVp0iT16NHDUEog8FAogWqUn5+vBx54QAsXLlROTk7F+s5msykhIUHdu3fX3/72N3Xr1s1wUsB3rVmzRs8884xWrVqlffv2VUz6bTabEhMTNXDgQD366KOKj483nBTwXxRKoApZlqVXX31Vzz//vDZv3nzCei4iIkIdOnTQfffdx/OPQDVavny5/t//+39av369CgsLKz7udDqVlpamsWPH6tZbb2ULAFQhCiVQSRs3btSkSZO0atUqFRQUVHw8KChITZo00ahRozRx4kQ5nU6DKYHAZFmWnnnmGb3yyivavn37CS+61apVS127dtVDDz2kLl26GEwJ+D4KJXAOFi1apEmTJumHH3444faZOnXqqF+/fnrsscc4+xHwQtnZ2Zo0aZI+/PBD5eXlVazH7Xa7mjdvrvvvv1/Dhg0znBLwPRRK4AzNmjVLTzzxhLZv317xLKTT6VTbtm11zz338IYp4IOWLl2qxx57TF999ZVKS0slHXv2smHDhrrjjjs0btw4VuPAGaBQAidxfFU2bdo0ZWVlVUwyQkND1b17d02dOlWtWrUynBJAVdmxY4fGjx+v5cuXn3CJQFJSkkaPHq1Jkybx6ApwEhRK4BdcLpcefPBBzZo1S7m5uRUfj4iIUN++ffXss88qJSXFYEIANSEvL08TJkzQBx98cMKz0bVr19aQIUP01FNPKTIy0mBCwLtQKBHwLMvSY489pueee0779++v+Hh0dLQGDRqkqVOnKi4uzmBCACYVFhbq3nvv1dtvv33C54hatWrphhtu0L/+9S8mlwh4FEoErCVLlmjChAnKyMioWGfXqVNHw4YN05NPPsm9wQB+w7IsPfLII5o5c6ays7MrPt6gQQM98sgjGjVqlLlwgEEUSgSUrKwsjR49Wp9//rnKysokSeHh4brmmmv0/PPPs8ICcMYsy9Jdd92lV199tWItbrfb1b59e7388stq27at2YBADaJQwu9ZlqWJEyfqtddeq7imzeFwqGPHjpoxYwYv1gCotOzsbP35z3/W8uXLKy40CA0N1aBBgzR9+nRFR0cbTghUL7vpAEB1eeutt9SoUSMFBQXp2Wef1eHDh5WSkqLZs2ervLxca9eupUwCqBLJycn673//q9LSUn366ac6//zzVVpaqrlz5yomJkYJCQl64oknTji3FvAnTCjhVwoKCnT99dfro48+qvjEXatWLY0YMUJTpkzhwXkANeqpp57SlClTtG/fPknHzrhs166d5s6dq6ZNmxpOB1QdCiX8wvLly/XnP/9ZmZmZko6ttHv27KlXXnmFG2sAGFdYWKibb75ZCxYsqDhAvU6dOnr88cc1ZswYw+mAyqNQwmdZlqX7779f06ZN09GjRyVJMTExuv/++zVx4kTD6QDg97333nsaN25cxVviQUFBuvLKK/XGG29wugR8FoUSPic7O1vXXXed1qxZU3EF4vnnn685c+bwViUAn5Gbm6thw4bp888/r/hc1rx5c73xxhvq1KmT4XTA2eGlHPiM+fPnq169eqpfv75WrVqloKAgDRs2TKWlpUpPT6dMAvApiYmJWr58uSzL0kMPPaSoqCht3bpVnTt3Vq1atfTwww+bjgicMSaU8Hp33nmnnnvuuYrnjhISEvTPf/5TI0aMMJwMAKrWunXrNHLkSGVkZEg6dq5lv379tGDBAtbh8GoUSngly7I0evRozZkzR5ZlyWazqWPHjnr77bd5yQaA3ysuLtaIESO0cOFClZeXS5K6du2q999/X/Hx8YbTAb/FyhtexeVy6corr5TT6dTrr78uj8ejq6++WiUlJfryyy8pkwACQlhYmN555x2VlZXpkUceUWhoqNauXauEhAS1bt264kQLwFswoYRXKCgo0ODBg7VixQpJx956vPHGG/Xiiy/K4XAYTgcA5k2fPl133XWXjhw5Iklq3LixFixYwPPj8AoUShiVm5urK664Qhs2bJAkOZ1OjR8/XpMnTzacDAC8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", "text/plain": [ "
" ] @@ -351,341 +357,248 @@ } ], "source": [ - "# Get node positions and colors\n", "pos = {node: (jx_graph.nodes[node]['x'], jx_graph.nodes[node]['y']) for node in jx_graph.nodes()}\n", - "\n", - "# Plot 1: Node indices\n", "node_colors = [jx_graph.nodes[node]['id'] for node in jx_graph.nodes()]\n", "nx.draw(jx_graph, pos=pos, node_color=node_colors, cmap='viridis', with_labels=True)" ] }, { "cell_type": "code", - "execution_count": 856, + "execution_count": 981, "metadata": {}, "outputs": [ { "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
branchtypeidxyzrl
10113.01.50.00.00.325
31112.00.00.00.01.000
52114.00.02.00.00.300
\n", + "
" + ], "text/plain": [ - "([array([0., 1.]), array([1., 2., 3.]), array([1., 4., 5., 6.])],\n", - " [array([1, 2, 3]), array([1]), array([1, 4, 5, 6])])" + " branch type id x y z r l\n", + "1 0 1 1 3.0 1.5 0.0 0.0 0.325\n", + "3 1 1 1 2.0 0.0 0.0 0.0 1.000\n", + "5 2 1 1 4.0 0.0 2.0 0.0 0.300" ] }, - "execution_count": 856, + "execution_count": 981, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "jx_branch_nodes, morph_branch_nodes" - ] - }, - { - "cell_type": "code", - "execution_count": 861, - "metadata": {}, - "outputs": [], - "source": [ - "morph_eq_jx = []\n", - "\n", - "for i, b in enumerate(jx_branch_nodes):\n", - " for j, mb in enumerate(morph_branch_nodes):\n", - " if len(b) == len(mb):\n", - " if np.allclose(b, mb):\n", - " morph_eq_jx.append((i,j))\n", - " break\n", - "if len(morph_eq_jx) > 0:\n", - " diff_morph_branches = [b for i, b in enumerate(morph_branch_nodes) if i not in np.array(morph_eq_jx)[:,1]]\n", - " diff_jx_branches = [b for j, b in enumerate(jx_branch_nodes) if j not in np.array(morph_eq_jx)[:,0]]\n", - "else:\n", - " print(\"No branches are equal\")\n", - " diff_morph_branches = morph_branch_nodes\n", - " diff_jx_branches = jx_branch_nodes" + "morph_comps.to_pandas()[0].loc[morph_comps.to_pandas()[0]['type'] == 1]" ] }, { "cell_type": "code", - "execution_count": 862, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABdEAAAHqCAYAAADrpwd3AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAL71JREFUeJzt3Xm4VXWh//HPOQdldgRBRRnVFAduerVfSoSzOFznoetAQmrmLJZDgaBp3UwUzHAo09JKc8gsRExuToV6HUNSsATlOiE5oQLnnP37g8uJA3zhqCACr9fz8Dyetdf+7u/mefC79nuvs1ZVpVKpBAAAAAAAWEj18p4AAAAAAAB8VonoAAAAAABQIKIDAAAAAECBiA4AAAAAAAUiOgAAAAAAFIjoAAAAAABQIKIDAAAAAECBiA4AAAAAAAUiOgAAAAAAFIjo8BnQpUuX9O/ff3lPY7HOP//8VFVVNdq2IswbAJirqqoqJ5100vKeBgB86vr37582bdos72ksN126dMk+++yzvKcBKzQRHRbws5/9LFVVVWnRokWmTZu20ONf/vKXs+WWWy6HmTXdijBHAFiW5q3njz32WCqVSnr37p327dvnzTffXGjfE044IauttlqefPLJxY7ZpUuXVFVVNfxp0aJFNtlkk5x11lmZMWPGMnonAPDZNW+9raqqyoMPPrjQ45VKJRtttFGqqqpW6Ij75S9/udExwOqrr56uXbvmuOOOy0svvbS8pwd8Cpot7wnAZ9WsWbPyve99LyNHjlzeU/nMeu6551Jd7bs4AD7bqqqqctVVV6VXr14ZNGhQrrvuuobH/vznP+fqq6/OGWeckV69ei1xrF69euXMM89Mknz44Yf5n//5n1x22WX505/+lEceeWRZvQUA+Exr0aJFbrrppuy0006Ntv/pT3/Kyy+/nObNmy+nmS09nTp1ysUXX5wkmT17dp599tmMGjUqY8aMycSJE9OqVavlPENgWRLRoaBXr1655pprcs4552SDDTZY3tP5TFoZDoQAWDVsscUWOeuss3LRRRelf//+6dOnT+bMmZPjjjsuG220UYYOHdqkcTbccMMceeSRDT8PHDgwbdq0ySWXXJJJkyZlk002KT535syZad269Sd+LwDwWdOvX7/ccsstGTFiRJo1+1dquummm7Lttttm+vTpS+216uvrM3v27LRo0WKpjdkUa665ZqNjgCTp2rVrTjrppDz00EPZbbfdis91DAArPqeQQsG5556burq6fO9731vivrW1tbngggvSvXv3NG/ePF26dMm5556bWbNmNdqvUqnkwgsvTKdOndKqVav07ds3EyZMWOSYb731Vk477bRstNFGad68eXr06JHvf//7qa+v/1jvZ951UO+4445sueWWad68eXr27Jm77757oX0ffPDB/Pu//3tatGiR7t2756qrrlrkmIu6Jvpbb72V008/PV26dEnz5s3TqVOnHH300Y0OmmbNmpUhQ4akR48ead68eTbaaKN885vfXOjva+zYsdlpp52y1lprpU2bNtlss81y7rnnfqz3DwDf+c530r179xx//PGZPXt2fvjDH+avf/1rrrjiik/0wbZjx45J0igazLv26gsvvJB+/fqlbdu2+c///M8kyQMPPJBDDjkkG2+8ccM6ePrpp+eDDz5oNO68MaZNm5b9998/bdq0Sfv27TNo0KDU1dU12re+vj6XX355ttpqq7Ro0SLt27fPnnvumccee2yh+TblWGDatGk59thj06FDh4b9fvrTny6038iRI9OzZ8+0atUqa6+9drbbbrvcdNNNH/0vEYAV2hFHHJE333wzY8eObdg2e/bs/OY3v8lXvvKVRT5n5syZOfPMMxs+82622Wa55JJLUqlUGu0377PsjTfemJ49e6Z58+a5++678+KLL6aqqiqXXHJJhg8fns6dO6dly5bp06dP/vrXvy7yNZuypn4UizoGmHc/sWeffTZf+cpXsvbaazecof/000+nf//+6datW1q0aJGOHTvm2GOPXehyc/PGmDx5cvr375+11lora665Zr761a/m/fffX2gev/jFL7L99ts3rMdf+tKXcs899yy034MPPpjtt98+LVq0SLdu3XLDDTcstE9TW8SvfvWrbLvttmnbtm3WWGONbLXVVrn88ss/+l8irCCciQ4FXbt2zdFHH51rrrkmZ5999mLPRh84cGCuv/76HHzwwTnzzDMzfvz4XHzxxZk4cWJuv/32hv0GDx6cCy+8MP369Uu/fv3y+OOPZ/fdd8/s2bMbjff++++nT58+mTZtWo4//vhsvPHGefjhh3POOefklVdeyWWXXfax3tODDz6Y2267LSeeeGLatm2bESNG5KCDDsrUqVOz7rrrJkmeeeaZ7L777mnfvn3OP//81NbWZsiQIenQocMSx3/vvffSu3fvTJw4Mccee2w+//nPZ/r06bnzzjvz8ssvp127dqmvr89+++2XBx98MMcdd1w233zzPPPMMxk+fHief/753HHHHUmSCRMmZJ999snWW2+dYcOGpXnz5pk8eXIeeuihj/XeAaBFixa58sors8cee+TEE0/MTTfdlAMOOCD77rtvk8eYM2dOwxfDH374YZ544olceuml+dKXvpSuXbs22re2tjZ77LFHdtppp1xyySUNv+Z9yy235P3338/Xv/71rLvuunnkkUcycuTIvPzyy7nlllsajVFXV5c99tgjO+ywQy655JLce++9+eEPf5ju3bvn61//esN+AwYMyM9+9rPstddeGThwYGpra/PAAw/kL3/5S7bbbruG/ZpyLPDaa6/lC1/4QkO0aN++fUaPHp0BAwbknXfeyWmnnZYkueaaa3LKKafk4IMPzqmnnpoPP/wwTz/9dMaPH18MJgCsnLp06ZL/9//+X375y19mr732SpKMHj06b7/9dg4//PCMGDGi0f6VSiX77bdfxo0blwEDBqRXr14ZM2ZMzjrrrEybNi3Dhw9vtP99992Xm2++OSeddFLatWuXLl26NDx2ww035N133803vvGNfPjhh7n88suz884755lnnmn0Obapa2pJXV1dwzHAnDlzMnHixIaTw3bccceF9j/kkEOyySab5KKLLmr4YmDs2LH5+9//nq9+9avp2LFjJkyYkKuvvjoTJkzIX/7yl1RVVTUa49BDD03Xrl1z8cUX5/HHH8+1116b9dZbL9///vcb9hk6dGjOP//8fPGLX8ywYcOy+uqrZ/z48bnvvvuy++67N+w3efLkHHzwwRkwYECOOeaY/PSnP03//v2z7bbbpmfPnkma3iLGjh2bI444IrvsskvDXCZOnJiHHnoop5566hL/LmGFVAEaue666ypJKo8++mjlhRdeqDRr1qxyyimnNDzep0+fSs+ePRt+fvLJJytJKgMHDmw0zqBBgypJKvfdd1+lUqlUXn/99crqq69e2XvvvSv19fUN+5177rmVJJVjjjmmYdsFF1xQad26deX5559vNObZZ59dqampqUydOnWx72HBOVYqlUqSyuqrr16ZPHlyw7annnqqkqQycuTIhm37779/pUWLFpUpU6Y0bHv22WcrNTU1lQX/l9G5c+dG8x48eHAlSeW2225baE7z3vPPf/7zSnV1deWBBx5o9PioUaMqSSoPPfRQpVKpVIYPH15JUnnjjTcW+14BYFHmX88XdMQRR1SSVNq2bVt56aWXmjxm586dK0kW+rPjjjtWpk+f3mjfY445ppKkcvbZZy80zvvvv7/QtosvvrhSVVXVaP2dN8awYcMa7ftv//ZvlW233bbh5/vuu6+SpNHxyjzzH3M09VhgwIABlfXXX3+h93T44YdX1lxzzYb5/8d//MdCxxsArFrmX2+vuOKKStu2bRvWiUMOOaTSt2/fSqUydw3de++9G553xx13VJJULrzwwkbjHXzwwZWqqqpGa1WSSnV1dWXChAmN9v3HP/5RSVJp2bJl5eWXX27YPn78+EqSyumnn96wralrakmfPn0WeQyw+eabV/7+97832nfIkCGVJJUjjjhioXEWdQzwy1/+spKkcv/99y80xrHHHtto3wMOOKCy7rrrNvw8adKkSnV1deWAAw6o1NXVNdp3/mOAeccw87/G66+/XmnevHnlzDPPbNjW1BZx6qmnVtZYY41KbW3twn9ZsJJyORdYjG7duuWoo47K1VdfnVdeeWWR+/zhD39IkpxxxhmNts+76djvf//7JMm9996b2bNn5+STT2707fK8s7nmd8stt6R3795Ze+21M3369IY/u+66a+rq6nL//fd/rPez6667pnv37g0/b7311lljjTXy97//Pcncb9bHjBmT/fffPxtvvHHDfptvvnn22GOPJY5/6623ZptttskBBxyw0GPz3vMtt9ySzTffPJ/73Ocavbedd945STJu3LgkyVprrZUk+e1vf/uxL2EDAIvSrl27JHOvk96pU6eP9NwddtghY8eOzdixY3PXXXflu9/9biZMmJD99ttvocuxJFnkmW0tW7Zs+O+ZM2dm+vTp+eIXv5hKpZInnnhiof1POOGERj/37t27Ye1O5q6/VVVVGTJkyELPXfCMtiUdC1Qqldx6663Zd999U6lUGq3Ve+yxR95+++08/vjjSeau1S+//HIeffTRRf5dAbBqOfTQQ/PBBx/krrvuyrvvvpu77rqr+JtJf/jDH1JTU5NTTjml0fYzzzwzlUolo0ePbrS9T58+2WKLLRY51v77758NN9yw4eftt98+O+ywQ8Nn9fktaU1dnC5dujQcA4wePTqXXXZZ3n777ey111554403lvhaSeNjgA8//DDTp0/PF77whSRpWF+XNN8333wz77zzTpK5l2irr6/P4MGDU13dOPEteAywxRZbpHfv3g0/t2/fPptttlmj99/UFrHWWmtl5syZjS7fAys7ER2W4Nvf/nZqa2uL10afMmVKqqur06NHj0bbO3bsmLXWWitTpkxp2C/JQjcca9++fdZee+1G2yZNmpS777477du3b/Rn1113TZK8/vrrH+u9zB/G51l77bXzz3/+M0nyxhtv5IMPPljkTdE222yzJY7/wgsvZMstt1zsPpMmTcqECRMWem+bbrppkn+9t8MOOyw77rhjBg4cmA4dOuTwww/PzTffLKgD8Ik89thj+dGPfpQtt9wy48ePzy9+8YuP9Px27dpl1113za677pq999475557bq699to8/PDDufbaaxvt26xZs0VG+qlTp6Z///5ZZ511Gq7J2qdPnyTJ22+/3Wjfedc3n9/8a3cyd/3dYIMNss466yxx/k05Fnjrrbdy9dVXL7RWf/WrX03yr7X6W9/6Vtq0aZPtt98+m2yySb7xjW+47BrAKmzeZ9abbropt912W+rq6nLwwQcvct8pU6Zkgw02SNu2bRtt33zzzRsen9+Cl0yb36I+v2666aZ58cUXG21rypq6OK1bt244Bthzzz1z6qmn5s4778xzzz23yF6wqDnPmDEjp556ajp06JCWLVumffv2DfsteAyQLLxuz2sH8+b8wgsvpLq6uvgFw+LGmjfe/O+/qS3ixBNPzKabbpq99tornTp1yrHHHrvIe6zAysQ10WEJunXrliOPPDJXX311zj777OJ+C37L+0nU19dnt912yze/+c1FPj4vOH9UNTU1i9xeWeDGLctSfX19ttpqq1x66aWLfHyjjTZKMvcb+vvvvz/jxo3L73//+9x999359a9/nZ133jn33HNP8b0AQEldXV2OO+64bLDBBnnooYey++6758wzz8w+++zT8BtQH8cuu+ySJLn//vtz8sknN2xv3rz5QmeF1dXVZbfddsuMGTPyrW99K5/73OfSunXrTJs2Lf3791/oy+Klvd4t6Vhg3usfeeSROeaYYxa579Zbb51kbuh47rnnctddd+Xuu+/OrbfemiuvvDKDBw/O0KFDl+q8AVgxfOUrX8nXvva1vPrqq9lrr70+0fo6v/nP4P64lsVnyG233TZrrrnmIn9bfFFzPvTQQ/Pwww/nrLPOSq9evdKmTZvU19dnzz33XOQJY0vzM3xTxmpqi1hvvfXy5JNPZsyYMRk9enRGjx6d6667LkcffXSuv/76jzw3WBGI6NAE3/72t/OLX/yi0c075uncuXPq6+szadKkhm/Nk7k35XrrrbfSuXPnhv2Sud/sduvWrWG/N954Y6Fvvrt375733nuv4dveT0v79u3TsmXLTJo0aaHHnnvuuSU+v3v37sW7oM+/z1NPPZVddtlliV88VFdXZ5dddskuu+ySSy+9NBdddFHOO++8jBs37lP/uwFgxTdixIg88cQTuf3227PGGmtk1KhR2W677XL22Wdn1KhRH3vc2traJHNvsL0kzzzzTJ5//vlcf/31Ofrooxu2f5Jfh+7evXvGjBmTGTNmNOls9MVp37592rZtm7q6uiatta1bt85hhx2Www47LLNnz86BBx6Y7373uznnnHPSokWLTzQXAFY8BxxwQI4//vj85S9/ya9//evifp07d869996bd999t9HZ6H/7298aHm+qRX1+ff755xvdfHRZqqura9IxwD//+c/88Y9/zNChQzN48OCG7Yuaf1N179499fX1efbZZ9OrV6+PPc784zW1Ray++urZd999s++++6a+vj4nnnhirrrqqnznO99Z6Df1YWXgci7QBN27d8+RRx6Zq666Kq+++mqjx/r165ckDXepnmfemdZ77713krnXIF1ttdUycuTIRt/0Lvi8ZO6303/+858zZsyYhR576623Gj6sL201NTXZY489cscdd2Tq1KkN2ydOnLjIuSzooIMOylNPPZXbb799ocfmvedDDz0006ZNyzXXXLPQPh988EFmzpyZZO6vuS1o3kHBrFmzmvR+AGCel156KYMHD85+++2X/fffP8ncdeWUU07JNddck/Hjx3/ssX/3u98lSbbZZpsl7jvvLLD5jwUqlUouv/zyj/36Bx10UCqVyiLP/v6oZ6rV1NTkoIMOyq233rrIL8bnv+brm2++2eix1VdfPVtssUUqlUrmzJnzkV4XgJVDmzZt8uMf/zjnn39+9t133+J+/fr1S11dXa644opG24cPH56qqqrstddeTX7NO+64I9OmTWv4+ZFHHsn48eM/0hgf17hx4/Lee+997GOAZNFNoKn233//VFdXZ9iwYQudyf5xzlZvaotY8Bigurq64TfVfF5nZeVMdGii8847Lz//+c/z3HPPpWfPng3bt9lmmxxzzDG5+uqr89Zbb6VPnz555JFHcv3112f//fdP3759k8w9s2vQoEG5+OKLs88++6Rfv3554oknMnr06IYbnM1z1lln5c4778w+++yT/v37Z9ttt83MmTPzzDPP5De/+U1efPHFhZ6ztAwdOjR33313evfunRNPPDG1tbUZOXJkevbsmaeffnqxzz3rrLPym9/8JoccckiOPfbYbLvttpkxY0buvPPOjBo1Kttss02OOuqo3HzzzTnhhBMybty47Ljjjqmrq8vf/va33HzzzRkzZky22267DBs2LPfff3/23nvvdO7cOa+//nquvPLKdOrUKTvttNMyee8ArLxOPvnkVCqVjBw5stH2oUOHNqxLjz322BJ/1XvatGkN11GfPXt2nnrqqVx11VVp165do0u5lHzuc59L9+7dM2jQoEybNi1rrLFGbr311iZfj3VR+vbtm6OOOiojRozIpEmTGn4l/IEHHkjfvn1z0kknfaTxvve972XcuHHZYYcd8rWvfS1bbLFFZsyYkccffzz33ntvwxfdu+++ezp27Jgdd9wxHTp0yMSJE3PFFVdk7733XugatwCsOkqXA5vfvvvum759++a8887Liy++mG222Sb33HNPfvvb3+a0005rdBPsJenRo0d22mmnfP3rX8+sWbNy2WWXZd111y1ekuTjevvttxuOAWpra/Pcc8/lxz/+cVq2bLnYS7/Os8Yaa+RLX/pS/uu//itz5szJhhtumHvuuSf/+Mc/PvacevTokfPOOy8XXHBBevfunQMPPDDNmzfPo48+mg022CAXX3zxRxqvqS1i4MCBmTFjRnbeeed06tQpU6ZMyciRI9OrV69Gv6EPKxMRHZqoR48eOfLIIxd5fa9rr7023bp1y89+9rPcfvvt6dixY84555wMGTKk0X4XXnhhWrRokVGjRjV8OL3nnnsazlafp1WrVvnTn/6Uiy66KLfccktuuOGGrLHGGtl0000zdOjQrLnmmsvsfW699dYZM2ZMzjjjjAwePDidOnXK0KFD88orrywxordp0yYPPPBAhgwZkttvvz3XX3991ltvveyyyy4NN1arrq7OHXfckeHDh+eGG27I7bffnlatWqVbt2459dRTG66xtt9+++XFF1/MT3/600yfPj3t2rVLnz59lvn7B2DlMO/sq5qamtxxxx357W9/m0suuWShm2q1bds2l19+eQ4++OCMGDEip59++mLHffLJJ3PUUUclmbumtWvXLgceeGAuuOCCbLjhhkuc12qrrZbf/e53OeWUU3LxxRenRYsWOeCAA3LSSSc16Sy2kuuuuy5bb711fvKTn+Sss87Kmmuume222y5f/OIXP/JYHTp0yCOPPJJhw4bltttuy5VXXpl11103PXv2bHRpu+OPPz433nhjLr300rz33nvp1KlTTjnllHz729/+2O8DgFVDdXV17rzzzgwePDi//vWvc91116VLly75wQ9+kDPPPPMjjXX00Uenuro6l112WV5//fVsv/32ueKKK7L++usv1Tm//PLLDccAVVVVWXvttdOnT58MGTKkyZdSuemmm3LyySfnRz/6USqVSnbfffeMHj06G2ywwcee17Bhw9K1a9eMHDky5513Xlq1apWtt966Ya4fRVNbxLz7xl155ZV566230rFjxxx22GE5//zzF7ofDKwsqiqf5h0FAQDgUzBixIiceuqpmTx58kc6mw0AWDG8+OKL6dq1a37wgx9k0KBBy3s6wErO10MAAKx0Hn300bRu3foj3ZgMAABgUVzOBQCAlcatt96a//7v/86NN96YgQMHplkzh7sAAMAn41MFAAArjUGDBuXdd9/NgAEDMnz48OU9HQAAYCXgmugAAAAAAFDgmugAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6AAAAAAAUiOgAAAAAAFAgogMAAAAAQIGIDgAAAAAABSI6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AABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUCCiAwAAAABAgYgOAAAAAAAFIjoAAAAAABSI6AAAAAAAUPD/AWz2c1EBAQcIAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "jx_subgraph = jx_graph.subgraph(np.unique(np.hstack(diff_morph_branches)))\n", - "\n", - "# Get node positions and colors\n", - "pos = {node: (jx_subgraph.nodes[node]['x'], jx_subgraph.nodes[node]['y']) for node in jx_subgraph.nodes()}\n", - "\n", - "# Create figure with 1x3 subplots\n", - "fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n", - "\n", - "# Plot 1: Node indices\n", - "node_colors = [jx_subgraph.nodes[node]['id'] for node in jx_subgraph.nodes()]\n", - "nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='viridis', with_labels=True, ax=axes[0])\n", - "axes[0].set_title('Node Indices')\n", - "\n", - "# Plot 2: JX branches\n", - "node_colors = np.zeros(len(jx_subgraph.nodes()))\n", - "for i, branch in enumerate(diff_jx_branches):\n", - " node_colors[np.isin(list(jx_subgraph.nodes()), branch)] = i + 1\n", - "nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='tab10', with_labels=True, ax=axes[1])\n", - "axes[1].set_title('JX Branches')\n", - "\n", - "# Plot 3: Morph branches\n", - "node_colors = np.zeros(len(jx_subgraph.nodes()))\n", - "for i, branch in enumerate(diff_morph_branches):\n", - " node_colors[np.isin(list(jx_subgraph.nodes()), branch)] = i + 1\n", - "nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='tab10', with_labels=True, ax=axes[2])\n", - "axes[2].set_title('Morph Branches')\n", - "\n", - "plt.tight_layout()\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 661, + "execution_count": 877, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Morph branches:\n", - "\n", - "JX branches:\n" + "testcase morph_3_types_single_point_soma.swc: 1, 1\n", + "testcase morph_3_types.swc: 0, 0\n", + "testcase morph_interrupted_soma.swc: 0, 0\n", + "testcase morph_soma_both_ends.swc: 0, 0\n", + "testcase morph_somatic_branchpoint.swc: 0, 0\n", + "testcase morph_non_somatic_branchpoint.swc: 0, 0\n", + "testcase morph_ca1_n120_single_point_soma.swc: 1, 1\n", + "testcase morph_ca1_n120.swc: 0, 0\n", + "testcase morph_l5pc_with_axon.swc: 0, 0\n", + "testcase morph_allen_485574832.swc: 1, 1\n" ] } ], "source": [ - "print(\"Morph branches:\")\n", - "for b in diff_morph_branches:\n", - " print([jx_graph.nodes[n][\"id\"] for n in b])\n", - "print()\n", - "print(\"JX branches:\")\n", - "for b in diff_jx_branches:\n", - " print([jx_graph.nodes[n][\"id\"] for n in b])\n" + "from jaxley.io.graph import build_compartment_graph, to_swc_graph, _trace_branches\n", + "\n", + "testcases = [ \n", + "\"morph_3_types_single_point_soma.swc\",\n", + "\"morph_3_types.swc\",\n", + "\"morph_interrupted_soma.swc\",\n", + "\"morph_soma_both_ends.swc\",\n", + "\"morph_somatic_branchpoint.swc\",\n", + "\"morph_non_somatic_branchpoint.swc\", # no soma!\n", + "\"morph_ca1_n120_single_point_soma.swc\",\n", + "\"morph_ca1_n120.swc\",\n", + "\"morph_l5pc_with_axon.swc\",\n", + "\"morph_allen_485574832.swc\",\n", + "]\n", + "\n", + "for i, testcase in enumerate(testcases):\n", + " jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcase)\n", + "\n", + " morph_branches = list_branches(MorphTree.from_nx(jx_graph.copy()))\n", + " morph_branch_nodes = [np.sort(b) for b in morph_branches]\n", + "\n", + " # do jx_trace after morph_traces, since jax_trace modifies the graph\n", + " jx_branches = _trace_branches(jx_graph.copy())[1]\n", + " jx_branch_nodes = [np.sort(np.unique(b[:, :-1])) for b in jx_branches]\n", + " if i in [0,6,9]: # single soma\n", + " jx_branch_nodes = [b-1 for b in jx_branch_nodes]\n", + "\n", + " morph_eq_jx = []\n", + "\n", + " for i, b in enumerate(jx_branch_nodes):\n", + " for j, mb in enumerate(morph_branch_nodes):\n", + " if len(b) == len(mb):\n", + " if np.allclose(b, mb):\n", + " morph_eq_jx.append((i,j))\n", + " break\n", + " if len(morph_eq_jx) > 0:\n", + " diff_morph_branches = [b for i, b in enumerate(morph_branch_nodes) if i not in np.array(morph_eq_jx)[:,1]]\n", + " diff_jx_branches = [b for j, b in enumerate(jx_branch_nodes) if j not in np.array(morph_eq_jx)[:,0]]\n", + " else:\n", + " print(\"No branches are equal\")\n", + " diff_morph_branches = morph_branch_nodes\n", + " diff_jx_branches = jx_branch_nodes\n", + " \n", + " # single soma handled differently and will lead to 1 diff branch\n", + " print(f\"testcase {testcase}: {len(diff_morph_branches)}, {len(diff_jx_branches)}\")" ] }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 867, "metadata": {}, "outputs": [], "source": [ - "# for i, b in enumerate(morph_branch_nodes):\n", - "# pos = [(morph_graph.nodes[n][\"x\"], morph_graph.nodes[n][\"y\"]) for n in b]\n", - "# plt.plot(*zip(*pos))\n", + "# from jaxley.io.graph import build_compartment_graph, to_swc_graph, _trace_branches\n", + "\n", + "# testcases = [ \n", + "# \"morph_3_types_single_point_soma.swc\",\n", + "# \"morph_3_types.swc\",\n", + "# \"morph_interrupted_soma.swc\",\n", + "# \"morph_soma_both_ends.swc\",\n", + "# \"morph_somatic_branchpoint.swc\",\n", + "# \"morph_non_somatic_branchpoint.swc\", # no soma!\n", + "# \"morph_ca1_n120_single_point_soma.swc\",\n", + "# \"morph_ca1_n120.swc\",\n", + "# \"morph_l5pc_with_axon.swc\",\n", + "# \"morph_allen_485574832.swc\",\n", + "# ]\n", + "\n", + "# jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[2])\n", + "\n", + "# morph_branches = list_branches(MorphTree.from_nx(jx_graph.copy()))\n", + "# morph_branch_nodes = [np.sort(b) for b in morph_branches]\n", + "\n", + "# # do jx_trace after morph_traces, since jax_trace modifies the graph\n", + "# jx_branches = _trace_branches(jx_graph.copy())[1]\n", + "# jx_branch_nodes = [np.sort(np.unique(b[:, :-1])) for b in jx_branches]\n", + "# # jx_branch_nodes = [b-1 for b in jx_branch_nodes]\n", + "\n", + "\n", + "# morph_eq_jx = []\n", "\n", "# for i, b in enumerate(jx_branch_nodes):\n", - "# pos = [(jx_graph.nodes[n][\"x\"], jx_graph.nodes[n][\"y\"]) for n in b]\n", - "# plt.plot(*zip(*pos))\n", - "# plt.show()\n", - " \n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2 2\n", - "2 2\n", - "2 2\n", - "2 2\n", - "2 2\n", - "2 2\n", - "2 2\n", - "2 2\n", - "2 2\n", - "2 2\n", - "2 2\n", - "3 2\n", - "3 3\n", - "3 3\n", - "3 3\n", - "3 3\n", - "3 3\n", - "3 3\n", - "3 3\n", - "3 3\n", - "3 3\n", - "3 3\n", - "3 3\n", - "3 3\n", - "3 3\n", - "4 3\n", - "4 4\n", - "4 4\n", - "4 4\n", - "4 4\n", - "4 4\n", - "4 4\n", - "4 5\n", - "5 5\n", - "5 5\n", - "5 5\n", - "5 5\n", - "5 5\n", - "5 5\n", - "6 6\n", - "6 6\n", - "6 6\n", - "6 6\n", - "6 6\n", - "6 7\n", - "7 7\n", - "7 7\n", - "7 7\n", - "7 7\n", - "7 7\n", - "7 7\n", - "7 7\n", - "8 8\n", - "8 8\n", - "8 8\n", - "9 9\n", - "9 9\n", - "9 9\n", - "9 9\n", - "9 9\n", - "9 9\n", - "9 10\n", - "10 10\n", - "10 10\n", - "10 10\n", - "10 11\n", - "11 11\n", - "11 11\n", - "11 11\n", - "11 11\n", - "11 12\n", - "12 12\n", - "12 12\n", - "12 12\n", - "12 12\n", - "12 12\n", - "12 13\n", - "13 13\n", - "13 14\n", - "14 14\n", - "14 14\n", - "14 14\n", - "14 14\n", - "14 14\n", - "14 14\n", - "14 14\n", - "14 15\n", - "15 15\n", - "15 15\n", - "15 15\n", - "15 15\n", - "15 15\n", - "15 16\n", - "16 16\n", - "16 17\n", - "17 17\n", - "17 18\n", - "18 18\n", - "18 18\n", - "18 20\n", - "20 20\n", - "20 20\n", - "20 20\n", - "20 20\n", - "20 21\n", - "21 21\n", - "21 22\n", - "22 22\n", - "22 22\n", - "22 23\n", - "23 23\n", - "23 23\n", - "23 23\n", - "23 24\n", - "24 24\n", - "24 24\n", - "24 25\n", - "25 25\n", - "25 25\n", - "25 26\n", - "26 26\n", - "26 27\n", - "26 27\n", - "27 27\n", - "27 28\n", - "27 28\n", - "28 29\n", - "28 30\n", - "29 30\n", - "30 31\n", - "30 32\n", - "31 33\n", - "32 33\n", - "33 34\n", - "33 36\n", - "36 36\n", - "36 38\n", - "38 40\n", - "40 41\n", - "41 41\n", - "41 47\n", - "47 47\n", - "47 51\n", - "51 51\n", - "51 52\n", - "52 53\n", - "53 56\n", - "56 56\n", - "56 56\n", - "56 57\n", - "57 62\n", - "62 65\n", - "65 67\n", - "67 139\n" - ] - } - ], - "source": [ - "for jx_l, morph_l in zip(sorted(jx_branch_lens), sorted(morph_branch_lens)):\n", - " print(jx_l, morph_l)" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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IiJiOibsgVGAERERCXTV1oHxzMDoNmoRERHxa9VmYH59lIB/RwT/rk5EREQaXrUeGM/DHHUJScxox44dWCwW1q9f7+tSRESkoVWfgVEPjIiIiJiCWz0w4ufKy8t9XYKIiPgb9cDIqejXrx8TJ05k0qRJNG/enLi4OF544QWKi4sZPXo0kZGRnHnmmXz44YeezyxfvpzevXsTEhJCQkICd999NxUVFTXOOWHCBCZNmkTLli0ZMGAAABaLhTlz5jBw4EDCwsI4/fTT+d///ndcTT/99BMXXXQR4eHhdO3alaysrIb/ByEiIo2rqgfGph4Y/2IYUF7c+C/DqHOpL7/8Mi1btmT16tVMnDiRW265hauvvprzzjuPdevWcckllzBy5EhKSkrYu3cvgwYNolevXnzzzTfMmTOHf/3rXzz00EPHnTM4OJgvvviCuXPnerZPnz6dYcOG8c0335CRkcHw4cPZvHlzjc/ec889/PnPf2b9+vWcddZZjBgxokZAEhGRJsCEPTAWw6jHb1kfKywsxOFwUFBQQFRUVI19paWlbN++nZSUFEJDQys3lhfDI4mNX+hf9kFwxEkf3q9fP1wuFytXrgTA5XLhcDgYOnQor7zyCgA5OTkkJCSQlZXFe++9x5tvvsnmzZuxWCr/oj377LNMnTqVgoICrFYr/fr1o7CwkHXr1tX4XhaLhZtvvpk5c+Z4tp177rn06NGDZ599lh07dpCSksI///lPxowZA8CmTZvo1KkTmzdvpkOHDsfVX+s/exER8X8vXAx7s2HEa1z4big7fynhzVvS6HlajFe/zYl+f9dVYMzAmMg555zj+bPNZqNFixZ06dLFsy0uLg6AvLw8Nm/eTFpamie8APTt25eioiL27Nnj2dazZ89av1daWtpx74+dgaleT0JCgud7i4hIE1J9ITuT9MAExtOog8IrZ0N88X3r+pGgoBrvLRZLjW1VYcV9dIrvZEREnPws0Inqqc/3FhERE6ixDkzlz3h/fxZSYAQYi6VOl3LMomPHjrz55psYhuEJF1988QWRkZG0adPmdz//1VdfccMNN9R437179warV0RE/FSNHpgyQLdRSwO69dZb2b17NxMnTuT777/nnXfe4f7772fKlClYT2Lqb8GCBfz73/9m69at3H///axevZoJEyY0QuUiIuJXamni1QyMNJjWrVvzwQcf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owBTzTPPPEPbtm0JDQ2lT58+rF692tclnZLMzEx69epFZGQksbGxDBkyhC1bttQ4prS0lPHjx9OiRQuaNWvGsGHDyM3N9VHF3vPoo49isViYNGmSZ1tTGuvevXu5/vrradGiBWFhYXTp0oW1a9d69huGwX333UdCQgJhYWGkp6ezbds2H1Zcdy6Xi+nTp5OSkkJYWBhnnHEGDz74YI1nqJh1nCtWrODyyy8nMTERi8XCwoULa+w/mXEdPHiQjIwMoqKiiI6OZsyYMRQVFTXiKH7ficbpdDqZOnUqXbp0ISIigsTERG644Qb27dtX4xxmGCf8/r/T6m6++WYsFgszZ86ssd0MYz2ZcW7evJkrrrgCh8NBREQEvXr1YteuXZ793vpZrABz1Ouvv86UKVO4//77WbduHV27dmXAgAHk5eX5urR6W758OePHj+err75iyZIlOJ1OLrnkEoqLiz3HTJ48mffee48FCxawfPly9u3bx9ChQ31Y9albs2YNzz33HOecc06N7U1lrIcOHaJv374EBQXx4YcfsmnTJv7+97/TvHlzzzGPPfYYs2bNYu7cuaxatYqIiAgGDBhAaWmpDyuvmxkzZjBnzhz+8Y9/sHnzZmbMmMFjjz3G7NmzPceYdZzFxcV07dqVZ555ptb9JzOujIwMNm7cyJIlS1i0aBErVqxg3LhxjTWEk3KicZaUlLBu3TqmT5/OunXreOutt9iyZQtXXHFFjePMME74/X+nVd5++22++uorEhMTj9tnhrH+3jh//PFHzj//fDp06MBnn33Gt99+y/Tp0wkNDfUc47WfxYYYhmEYvXv3NsaPH+9573K5jMTERCMzM9OHVXlXXl6eARjLly83DMMw8vPzjaCgIGPBggWeYzZv3mwARlZWlq/KPCWHDx822rVrZyxZssS48MILjdtvv90wjKY11qlTpxrnn3/+b+53u91GfHy88fjjj3u25efnGyEhIcarr77aGCV6xWWXXWbcdNNNNbYNHTrUyMjIMAyj6YwTMN5++23P+5MZ16ZNmwzAWLNmjeeYDz/80LBYLMbevXsbrfa6OHactVm9erUBGDt37jQMw5zjNIzfHuuePXuM1q1bGxs2bDBOO+0046mnnvLsM+NYaxvntddea1x//fW/+Rlv/izWDAxQXl5OdnY26enpnm1Wq5X09HSysrJ8WJl3FRQUABATEwNAdnY2Tqezxrg7dOhAcnKyacc9fvx4LrvsshpjgqY11nfffZfU1FSuvvpqYmNj6d69Oy+88IJn//bt28nJyakxVofDQZ8+fUw11vPOO4+lS5eydetWAL755hs+//xzBg4cCDSdcR7rZMaVlZVFdHQ0qampnmPS09OxWq2sWrWq0Wv2loKCAiwWC9HR0UDTGqfb7WbkyJHceeeddOrU6bj9TWGsbreb999/n7POOosBAwYQGxtLnz59alxm8ubPYgUY4MCBA7hcLuLi4mpsj4uLIycnx0dVeZfb7WbSpEn07duXzp07A5CTk0NwcLDnh0UVs477tddeY926dWRmZh63rymN9aeffmLOnDm0a9eOjz76iFtuuYXbbruNl19+GcAzHrP/fb777rsZPnw4HTp0ICgoiO7duzNp0iQyMjKApjPOY53MuHJycoiNja2x3263ExMTY9qxl5aWMnXqVEaMGOF58F9TGueMGTOw2+3cdtttte5vCmPNy8ujqKiIRx99lEsvvZSPP/6YK6+8kqFDh7J8+XLAuz+LTfk0aqm78ePHs2HDBj7//HNfl9Igdu/eze23386SJUtqXGttitxuN6mpqTzyyCMAdO/enQ0bNjB37lxGjRrl4+q854033mDevHnMnz+fTp06sX79eiZNmkRiYmKTGqdUNvRec801GIbBnDlzfF2O12VnZ/P000+zbt06LBaLr8tpMG63G4DBgwczefJkALp168aXX37J3LlzufDCC736/TQDA7Rs2RKbzXZcF3Rubi7x8fE+qsp7JkyYwKJFi/j0009p06aNZ3t8fDzl5eXk5+fXON6M487OziYvL48ePXpgt9ux2+0sX76cWbNmYbfbiYuLazJjTUhI4Oyzz66xrWPHjp4u/6rxmP3v85133umZhenSpQsjR45k8uTJnhm2pjLOY53MuOLj44+7waCiooKDBw+abuxV4WXnzp0sWbLEM/sCTWecK1euJC8vj+TkZM/Pp507d3LHHXfQtm1boGmMtWXLltjt9t/9+eStn8UKMEBwcDA9e/Zk6dKlnm1ut5ulS5eSlpbmw8pOjWEYTJgwgbfffptly5aRkpJSY3/Pnj0JCgqqMe4tW7awa9cu0427f//+fPfdd6xfv97zSk1NJSMjw/PnpjLWvn37Hnc7/NatWznttNMASElJIT4+vsZYCwsLWbVqlanGWlJSgtVa80eUzWbz/F9eUxnnsU5mXGlpaeTn55Odne05ZtmyZbjdbvr06dPoNddXVXjZtm0bn3zyCS1atKixv6mMc+TIkXz77bc1fj4lJiZy55138tFHHwFNY6zBwcH06tXrhD+fvPp7p04tv03Ya6+9ZoSEhBgvvfSSsWnTJmPcuHFGdHS0kZOT4+vS6u2WW24xHA6H8dlnnxk///yz51VSUuI55uabbzaSk5ONZcuWGWvXrjXS0tKMtLQ0H1btPdXvQjKMpjPW1atXG3a73Xj44YeNbdu2GfPmzTPCw8ON//73v55jHn30USM6Otp45513jG+//dYYPHiwkZKSYhw5csSHldfNqFGjjNatWxuLFi0ytm/fbrz11ltGy5YtjbvuustzjFnHefjwYePrr782vv76awMwnnzySePrr7/23H1zMuO69NJLje7duxurVq0yPv/8c6Ndu3bGiBEjfDWkWp1onOXl5cYVV1xhtGnTxli/fn2Nn1FlZWWec5hhnIbx+/9Oj3XsXUiGYY6x/t4433rrLSMoKMh4/vnnjW3bthmzZ882bDabsXLlSs85vPWzWAGmmtmzZxvJyclGcHCw0bt3b+Orr77ydUmnBKj19eKLL3qOOXLkiHHrrbcazZs3N8LDw40rr7zS+Pnnn31XtBcdG2Ca0ljfe+89o3PnzkZISIjRoUMH4/nnn6+x3+12G9OnTzfi4uKMkJAQo3///saWLVt8VG39FBYWGrfffruRnJxshIaGGqeffrpxzz331PjlZtZxfvrpp7X+tzlq1CjDME5uXL/88osxYsQIo1mzZkZUVJQxevRo4/Dhwz4YzW870Ti3b9/+mz+jPv30U885zDBOw/j9f6fHqi3AmGGsJzPOf/3rX8aZZ55phIaGGl27djUWLlxY4xze+llsMYxqy1qKiIiImIB6YERERMR0FGBERETEdBRgRERExHQUYERERMR0FGBERETEdBRgRERExHQUYERERMR0FGBERETEdBRgRERExHQUYERERMR0FGBERETEdBRgRERExHT+P8ayTRYnHRwBAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(np.sort(jx_branch_lens), label=\"jx\")\n", - "plt.plot(np.sort(morph_branch_lens), label=\"morph\")\n", - "plt.legend()\n", - "plt.show()" + "# for j, mb in enumerate(morph_branch_nodes):\n", + "# if len(b) == len(mb):\n", + "# if np.allclose(b, mb):\n", + "# morph_eq_jx.append((i,j))\n", + "# break\n", + "# if len(morph_eq_jx) > 0:\n", + "# diff_morph_branches = [b for i, b in enumerate(morph_branch_nodes) if i not in np.array(morph_eq_jx)[:,1]]\n", + "# diff_jx_branches = [b for j, b in enumerate(jx_branch_nodes) if j not in np.array(morph_eq_jx)[:,0]]\n", + "# else:\n", + "# print(\"No branches are equal\")\n", + "# diff_morph_branches = morph_branch_nodes\n", + "# diff_jx_branches = jx_branch_nodes\n", + "\n", + "# jx_subgraph = jx_graph.subgraph(np.unique(np.hstack(diff_morph_branches)))\n", + "\n", + "# # Get node positions and colors\n", + "# pos = {node: (jx_subgraph.nodes[node]['x'], jx_subgraph.nodes[node]['y']) for node in jx_subgraph.nodes()}\n", + "\n", + "# # Create figure with 1x3 subplots\n", + "# fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n", + "\n", + "# # Plot 1: Node indices\n", + "# node_colors = [jx_subgraph.nodes[node]['id'] for node in jx_subgraph.nodes()]\n", + "# nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='viridis', with_labels=True, ax=axes[0])\n", + "# axes[0].set_title('Node Indices')\n", + "\n", + "# # Plot 2: JX branches\n", + "# node_colors = np.zeros(len(jx_subgraph.nodes()))\n", + "# for i, branch in enumerate(diff_jx_branches):\n", + "# node_colors[np.isin(list(jx_subgraph.nodes()), branch)] = i + 1\n", + "# nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='tab10', with_labels=True, ax=axes[1])\n", + "# axes[1].set_title('JX Branches')\n", + "\n", + "# # Plot 3: Morph branches\n", + "# node_colors = np.zeros(len(jx_subgraph.nodes()))\n", + "# for i, branch in enumerate(diff_morph_branches):\n", + "# node_colors[np.isin(list(jx_subgraph.nodes()), branch)] = i + 1\n", + "# nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='tab10', with_labels=True, ax=axes[2])\n", + "# axes[2].set_title('Morph Branches')\n", + "\n", + "# plt.tight_layout()\n", + "# plt.show()" ] }, { From 93cef1e97d37e741ec4519271cca7d7025d41d1e Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Fri, 23 May 2025 18:24:47 +0200 Subject: [PATCH 03/24] wip: save wip --- dev.ipynb | 72 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index 1032a411a..76dc86ddf 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 989, + "execution_count": 1015, "metadata": {}, "outputs": [], "source": [ @@ -151,9 +151,9 @@ "\n", "def list_branches(tree: MorphTree, return_branchpoints: bool = False) -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", " G = tree.to_nx().to_undirected()\n", - " branches: List[List[int]] = []\n", - " branchpoints: Set[int] = set()\n", - " visited: Set[Tuple[int, int]] = set()\n", + " branches = []\n", + " branchpoints = set()\n", + " visited = set()\n", "\n", " def is_branchpoint(n: int) -> bool:\n", " is_leaf = G.degree(n) <= 1\n", @@ -214,53 +214,55 @@ "\n", "def compartmentalize(tree: MorphTree, num_comps: int = 1) -> MorphTree:\n", " branches = list_branches(tree)\n", - " nodes_df, _ = tree.to_pandas()\n", - " nodes_df = nodes_df.astype(float)\n", + " nodes_df = tree.to_pandas()[0].astype(float)\n", "\n", - " new_inds = len(branches)*num_comps\n", + " # create new set of indices which arent already used as node indices to label comps\n", " existing_inds = set(nodes_df.index)\n", - " proposed_new_inds = set(range(len(branches)*num_comps + len(existing_inds)))\n", - " new_inds = list(proposed_new_inds.difference(existing_inds))\n", + " num_new_inds = len(branches)*num_comps\n", + " proposed_inds = set(range(num_new_inds + len(existing_inds)))\n", + " comp_inds = list(proposed_inds - existing_inds) # avoid overlap w. node indices\n", " \n", - " branch_nodes: List[np.ndarray] = []\n", - " branch_edges: List[List[Tuple[int, int]]] = []\n", - " for i, b in enumerate(branches):\n", - " branch_node_attrs = nodes_df.loc[b]\n", - " xyz_i = branch_node_attrs[[\"x\", \"y\", \"z\"]]\n", - " pathlen = ((xyz_i.diff(axis=0).fillna(0)**2).sum(axis=1)**.5)\n", - " branch_node_attrs[\"l\"] = pathlen.cumsum()\n", + " v_interp = vmap(jnp.interp, in_axes=(None, None, 1), out_axes=1)\n", + " \n", + " # collect comps and comp_edges\n", + " branch_nodes, branch_edges = [], []\n", + " for i, branch in enumerate(branches):\n", + " node_attrs = nodes_df.loc[branch]\n", + " xyz_i = node_attrs[[\"x\", \"y\", \"z\"]]\n", + " edge_lens = ((xyz_i.diff(axis=0).fillna(0)**2).sum(axis=1)**.5)\n", + " node_attrs[\"l\"] = edge_lens.cumsum() # path length\n", " \n", " # For single-point somatata, we set l = 2*r this ensures\n", " # A_cylinder = 2*pi*r*l = 4*pi*r^2 = A_sphere.\n", - " if len(b) == 1:\n", - " branch_node_attrs = branch_node_attrs.loc[b*2] # duplicate soma node\n", - " radius = branch_node_attrs[\"r\"].iloc[0]\n", - " branch_node_attrs[\"l\"] = np.array([0, 2*radius])\n", - "\n", - " v_interp = vmap(jnp.interp, in_axes=(None, None, 1), out_axes=1)\n", + " if len(branch) == 1:\n", + " node_attrs = node_attrs.loc[branch*2] # duplicate soma node\n", + " radius = node_attrs[\"r\"].iloc[0]\n", + " node_attrs[\"l\"] = np.array([0, 2*radius])\n", "\n", - " branch_len = max(branch_node_attrs[\"l\"])\n", + " branch_id = node_attrs[\"id\"].iloc[-1] # TODO: handle multi ids within branch!\n", + " branch_len = max(node_attrs[\"l\"])\n", " comp_len = branch_len / num_comps\n", - " comp_locs = jnp.linspace(comp_len/2, branch_len - comp_len/2, num_comps)\n", + " comp_locs = list(np.linspace(comp_len/2, branch_len - comp_len/2, num_comps))\n", " \n", - " x = jnp.array([0] + list(comp_locs) + [branch_len])\n", - " xp = jnp.array(branch_node_attrs[\"l\"].values)\n", - " fp = jnp.array(branch_node_attrs[[\"x\", \"y\", \"z\", \"r\"]].values)\n", + " x = jnp.array([0] + comp_locs + [branch_len]) # 0, branch_len = branchpoints\n", + " xp = jnp.array(node_attrs[\"l\"].values)\n", + " fp = jnp.array(node_attrs[[\"x\", \"y\", \"z\", \"r\"]].values)\n", "\n", " # Create node indices and attributes\n", - " node_attrs = np.array([\n", - " [b[0]] + new_inds[i:i+num_comps] + [b[-1]], # indices\n", + " comp_inds = [branch[0]] + comp_inds[i:i+num_comps] + [branch[-1]]\n", + " new_node_attrs = np.array([\n", + " comp_inds, # indices\n", " [i]*(num_comps+2), # branch indices\n", - " [0] + [1]*num_comps + [0], # types (0=branchpoint, 1=compartment)\n", - " [-1] + [branch_node_attrs[\"id\"].iloc[-1]]*num_comps + [-1], # ids\n", + " [0] + [1]*num_comps + [0], # types (0=branchpoint, 1=comp)\n", + " [-1] + [branch_id]*num_comps + [-1], # ids\n", " [0] + [comp_len]*num_comps + [0] # lengths\n", " ]).T\n", " \n", " # Interpolate xyzr coordinates and combine with attributes\n", - " comp_xyzr = np.hstack([node_attrs, np.array(v_interp(x, xp, fp))])\n", + " comp_xyzr = np.hstack([new_node_attrs, np.array(v_interp(x, xp, fp))])\n", " \n", " # Store edges and nodes\n", - " branch_edges.append(list(zip(node_attrs[:-1, 0], node_attrs[1:, 0])))\n", + " branch_edges.append(list(zip(comp_inds[:-1], comp_inds[1:])))\n", " branch_nodes.append(comp_xyzr)\n", "\n", " branch_nodes = jnp.concatenate(branch_nodes)\n", @@ -284,7 +286,7 @@ }, { "cell_type": "code", - "execution_count": 990, + "execution_count": 1017, "metadata": {}, "outputs": [], "source": [ @@ -315,7 +317,7 @@ }, { "cell_type": "code", - "execution_count": 991, + "execution_count": 1018, "metadata": {}, "outputs": [], "source": [ From 329b01be5c7e3a1f7a76f032c71778db7905977f Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Sat, 24 May 2025 13:01:52 +0200 Subject: [PATCH 04/24] wip: compartmentalization also seems to work --- dev.ipynb | 100 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index 76dc86ddf..f2486bb0a 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 1015, + "execution_count": 1127, "metadata": {}, "outputs": [], "source": [ @@ -155,7 +155,7 @@ " branchpoints = set()\n", " visited = set()\n", "\n", - " def is_branchpoint(n: int) -> bool:\n", + " def is_branchpoint_or_tip(n: int) -> bool:\n", " is_leaf = G.degree(n) <= 1\n", " is_branching = G.degree(n) > 2\n", " if G.degree(n) == 2:\n", @@ -186,7 +186,7 @@ " while G.degree(succ) == 2:\n", " next_node = next(n for n in G.neighbors(succ) if n != path[-2])\n", "\n", - " if in_visited(succ, next_node) or is_branchpoint(succ):\n", + " if in_visited(succ, next_node) or is_branchpoint_or_tip(succ):\n", " break\n", " \n", " path.append(next_node)\n", @@ -201,7 +201,7 @@ " if single_soma and is_soma(node):\n", " branches.append([node])\n", "\n", - " elif is_branchpoint(node):\n", + " elif is_branchpoint_or_tip(node):\n", " branchpoints.add(node)\n", " for succ in G.neighbors(node):\n", " if not in_visited(node, succ):\n", @@ -220,10 +220,13 @@ " existing_inds = set(nodes_df.index)\n", " num_new_inds = len(branches)*num_comps\n", " proposed_inds = set(range(num_new_inds + len(existing_inds)))\n", - " comp_inds = list(proposed_inds - existing_inds) # avoid overlap w. node indices\n", + " proposed_comp_inds = list(proposed_inds - existing_inds) # avoid overlap w. node indices\n", " \n", " v_interp = vmap(jnp.interp, in_axes=(None, None, 1), out_axes=1)\n", " \n", + " nodes_in_edges, node_counts_in_edges = np.unique(tree.edges, return_counts=True)\n", + " tip_node_inds = nodes_in_edges[node_counts_in_edges == 1]\n", + "\n", " # collect comps and comp_edges\n", " branch_nodes, branch_edges = [], []\n", " for i, branch in enumerate(branches):\n", @@ -244,26 +247,30 @@ " comp_len = branch_len / num_comps\n", " comp_locs = list(np.linspace(comp_len/2, branch_len - comp_len/2, num_comps))\n", " \n", - " x = jnp.array([0] + comp_locs + [branch_len]) # 0, branch_len = branchpoints\n", - " xp = jnp.array(node_attrs[\"l\"].values)\n", - " fp = jnp.array(node_attrs[[\"x\", \"y\", \"z\", \"r\"]].values)\n", - "\n", " # Create node indices and attributes\n", - " comp_inds = [branch[0]] + comp_inds[i:i+num_comps] + [branch[-1]]\n", - " new_node_attrs = np.array([\n", - " comp_inds, # indices\n", - " [i]*(num_comps+2), # branch indices\n", - " [0] + [1]*num_comps + [0], # types (0=branchpoint, 1=comp)\n", - " [-1] + [branch_id]*num_comps + [-1], # ids\n", - " [0] + [comp_len]*num_comps + [0] # lengths\n", - " ]).T\n", + " # branch_inds, comp_type, comp_id, comp_len\n", + " branch_tips = branch[0], branch[-1]\n", + " branch_tip_attrs = [i, -1, -1, 0]\n", + " comp_attrs = [i, 0, branch_id, comp_len] # comp_type: -1: branchpoint, 0: compartment\n", + "\n", + " comp_inds = proposed_comp_inds[i*num_comps:(i+1)*num_comps]\n", + " comp_inds = np.array([branch_tips[0], *comp_inds, branch_tips[1]])\n", + " comp_attrs = np.array([branch_tip_attrs] + [comp_attrs]*num_comps + [branch_tip_attrs])\n", + " comp_attrs = np.hstack([comp_inds[:, None], comp_attrs])\n", " \n", " # Interpolate xyzr coordinates and combine with attributes\n", - " comp_xyzr = np.hstack([new_node_attrs, np.array(v_interp(x, xp, fp))])\n", + " x = jnp.array([0] + comp_locs + [branch_len]) # 0, branch_len = branchpoints\n", + " xp = jnp.array(node_attrs[\"l\"].values)\n", + " fp = jnp.array(node_attrs[[\"x\", \"y\", \"z\", \"r\"]].values)\n", + " comp_attrs = np.hstack([comp_attrs, np.array(v_interp(x, xp, fp))])\n", " \n", + " # remove tip nodes\n", + " comp_attrs = comp_attrs[1:] if branch_tips[0] in tip_node_inds else comp_attrs\n", + " comp_attrs = comp_attrs[:-1] if branch_tips[1] in tip_node_inds else comp_attrs\n", + "\n", " # Store edges and nodes\n", - " branch_edges.append(list(zip(comp_inds[:-1], comp_inds[1:])))\n", - " branch_nodes.append(comp_xyzr)\n", + " branch_edges.append(list(zip(comp_attrs[:-1, 0], comp_attrs[1:, 0])))\n", + " branch_nodes.append(comp_attrs)\n", "\n", " branch_nodes = jnp.concatenate(branch_nodes)\n", " comp_attrs_keys = [\"idx\", \"branch\", \"type\", \"id\", \"x\", \"y\", \"z\", \"r\", \"l\"]\n", @@ -278,15 +285,16 @@ " comps = jnp.array(comp_df.index)\n", " comp_attrs = comp_df.to_dict(orient=\"records\")\n", " comp_edges = jnp.array(sum(branch_edges, []))\n", + " comp_edge_attrs = [{\"type\": -1} for _ in comp_edges]\n", "\n", - " comp_tree = MorphTree(comps, comp_edges, comp_attrs)\n", + " comp_tree = MorphTree(comps, comp_edges, comp_attrs, comp_edge_attrs)\n", " comp_tree = comp_tree.reindex_nodes(jnp.arange(len(comps)))\n", " return comp_tree" ] }, { "cell_type": "code", - "execution_count": 1017, + "execution_count": 1128, "metadata": {}, "outputs": [], "source": [ @@ -296,11 +304,11 @@ " self.states = {\"m\": 0.5, \"h\": 0.5}\n", "\n", "def dummy_insert(tree, inds, channel):\n", - " # TODO: where to store the equiv of self.channels, i.e. in module or in tree.global_attrs?\n", - " # Should Module and MorphTree be separate or the same thing?\n", + " # TODO: Should Module and MorphTree be separate or the same thing?\n", " for i in inds:\n", " tree.node_attrs[i].update(channel.params)\n", " tree.node_attrs[i].update(channel.states)\n", + " tree.global_attrs[\"channels\"].append(channel)\n", "\n", "def dummy_set(tree, inds, key, value):\n", " for i in inds:\n", @@ -317,7 +325,7 @@ }, { "cell_type": "code", - "execution_count": 1018, + "execution_count": 1132, "metadata": {}, "outputs": [], "source": [ @@ -336,12 +344,52 @@ "\"morph_allen_485574832.swc\",\n", "]\n", "\n", - "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[0])\n", + "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[-3])\n", "\n", "morph_comps = compartmentalize(MorphTree.from_nx(jx_graph.copy()), num_comps=1)\n", "jx_comps = build_compartment_graph(jx_graph, ncomp=1)" ] }, + { + "cell_type": "code", + "execution_count": 1133, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "MorphTree(nodes=233*['branch', 'type', 'id', 'x', 'y', 'z', 'r', 'l'], edges=232*['type'])" + ] + }, + "execution_count": 1133, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "morph_comps" + ] + }, + { + "cell_type": "code", + "execution_count": 1135, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "233" + ] + }, + "execution_count": 1135, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(jx_comps.nodes)" + ] + }, { "cell_type": "code", "execution_count": 899, From 527224be8b4ea22eb9be71fe8231a2cc4b430f2c Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Sat, 24 May 2025 13:16:20 +0200 Subject: [PATCH 05/24] wip: new graph matches old graph --- dev.ipynb | 63 +++++++++++++------------------------------------------ 1 file changed, 14 insertions(+), 49 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index f2486bb0a..710c9ba06 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 1127, + "execution_count": 1171, "metadata": {}, "outputs": [], "source": [ @@ -224,6 +224,7 @@ " \n", " v_interp = vmap(jnp.interp, in_axes=(None, None, 1), out_axes=1)\n", " \n", + " # identify tip nodes (degree == 1)\n", " nodes_in_edges, node_counts_in_edges = np.unique(tree.edges, return_counts=True)\n", " tip_node_inds = nodes_in_edges[node_counts_in_edges == 1]\n", "\n", @@ -262,6 +263,7 @@ " x = jnp.array([0] + comp_locs + [branch_len]) # 0, branch_len = branchpoints\n", " xp = jnp.array(node_attrs[\"l\"].values)\n", " fp = jnp.array(node_attrs[[\"x\", \"y\", \"z\", \"r\"]].values)\n", + " #TODO: interpolate r differently!\n", " comp_attrs = np.hstack([comp_attrs, np.array(v_interp(x, xp, fp))])\n", " \n", " # remove tip nodes\n", @@ -273,7 +275,7 @@ " branch_nodes.append(comp_attrs)\n", "\n", " branch_nodes = jnp.concatenate(branch_nodes)\n", - " comp_attrs_keys = [\"idx\", \"branch\", \"type\", \"id\", \"x\", \"y\", \"z\", \"r\", \"l\"]\n", + " comp_attrs_keys = [\"idx\", \"branch\", \"type\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", " int_cols = [\"idx\", \"branch\", \"type\", \"id\"]\n", " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", @@ -294,7 +296,7 @@ }, { "cell_type": "code", - "execution_count": 1128, + "execution_count": 1172, "metadata": {}, "outputs": [], "source": [ @@ -325,7 +327,7 @@ }, { "cell_type": "code", - "execution_count": 1132, + "execution_count": 1185, "metadata": {}, "outputs": [], "source": [ @@ -352,52 +354,12 @@ }, { "cell_type": "code", - "execution_count": 1133, + "execution_count": 1186, "metadata": {}, "outputs": [ { "data": { - "text/plain": [ - "MorphTree(nodes=233*['branch', 'type', 'id', 'x', 'y', 'z', 'r', 'l'], edges=232*['type'])" - ] - }, - "execution_count": 1133, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "morph_comps" - ] - }, - { - "cell_type": "code", - "execution_count": 1135, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "233" - ] - }, - "execution_count": 1135, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(jx_comps.nodes)" - ] - }, - { - "cell_type": "code", - "execution_count": 899, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAApQAAAHzCAYAAACe1o1DAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAVFZJREFUeJzt3XucznX+//HndV0z15zNgRkzhnEag0JyFks5VlrSgU1CWak2m6W22tL5V2mzanWSlKI2iiTZpCiHSClpCoOG0ZhhGIYxh2vmc12/P3zNpnKcw/s6PO63W7fvbcdhn3zbmee8Xp/P+23zeDweAQAAAOfIbjoAAAAAfBuFEgAAAJVCoQQAAEClUCgBAABQKRRKAAAAVAqFEgAAAJVCoQQAAEClUCgBAABQKRRKAAAAVAqFEgAAAJVCoQQAAEClUCgBAABQKRRKAAAAVAqFEgAAAJVCoQQAAEClUCgBAABQKRRKAAAAVAqFEgAAAJVCoQQAAEClUCgBAABQKRRKAAAAVAqFEgAAAJVCoQQAAEClUCgBAABQKRRKAAAAVAqFEgAAAJVCoQQAAEClUCgBAABQKRRKAAAAVAqFEgAAAJVCoQQAAEClUCgBAABQKRRKAAAAVAqFEgAAAJVCoQQAAEClUCgBAABQKRRKAAAAVAqFEgAAAJVCoQQQ8D777DM5HA61bdtWubm5puMAgM+hUAIIeIsWLZLb7dZ3332npKQkXXjhhRRLADgLQaYDAIAJhYWFKigokMvl0qFDh074sY0bNyopKUmpqan69NNPZVmW9u7dK7vdLofDoeDgYNntdjmdzor/7HQ6FRcXJ6fTaeYPBAAG2Twej8d0CAD4PS6XSz/++KPS09O1bds27dy5U3v27NGBAwdUXFyskpISuVwuuVwulZeXV/zjdrsr/vF4PDL5ac5ms53wj8PhkN1uV1BQkIKCgirKaEhIiEJDQxUREaGEhAQlJyercePGSktLU5s2bdSoUSM5HA5jfw4AOBUKJYAaUVxcrBUrVujLL7/UTz/9pJycHO3fv18FBQUqLCxUcXGxysrKKgrh2TjT0na8uIWFhSk8PFxOp1NBQUHaunWrdu3a9Zvf126366GHHlJJSYm2bt0qy7Lk8Xh+9/9alqWSkhIVFRWppKREpaWlKi0trfgzVVXZtdlsFX82p9OpsLAwRUVFKTY2VgkJCapXr55SU1PVs2dPdezYkRIKoEZQKAFUWn5+vj799FOtXbtWP/74o3bt2qX9+/ersLBQLpfrtAXxlyUpJCRE4eHhJ5SkBg0aqFGjRmrRooVat26tlJSUKi1KEyZM0NSpUyv+c3h4uJ5++mndeuutVfbfcaZcLpe2bNmi9PT0iqKbk5OjvLw8HTp0qKJ8H5/Knkn5djgcCgkJUXR0tOLj49W4cWO1bt1aXbt21SWXXKKwsLAa+JMB8GcUSgCnlZGRoXnz5mn16tXasWOH8vPzdfToUblcrlNO2IKCghQWFqaYmBglJiYqNTVVrVu3VuvWrdWmTRulpKTU4J/i5N544w2NHDnSaJGsLMuylJGRofT0dG3cuFE//PCDdu7cqX379qmgoEClpaWyLOukv/74M6GRkZGqU6eOWrRooZ49e+raa69VcnJyDf5JAPgiCiUASVJeXp7mzp2rFStW6Mcff1ROTo4KCwt/t4TYbDYFBwcrPDxcsbGxSk5OVrNmzdSuXTv17t1bLVu2NPAnqBzLsgJiPWxZlr766iutXLlSGzdu1Pbt25Wbm6uCggIVFRWpvLz8d39dUFCQatWqpXr16qlNmzbq27evBg8erOjo6Br+EwDwRhRKIIC4XC699957+u9//6uNGzfq559/1uHDh1VWVvabn2uz2RQWFqY6deooNTVVF110ka6++mq1bdu25oOjRlmWpVWrVmnRokVav369fvrpJx08eFClpaW/O5F2Op2KiYlRgwYN1K5dO11xxRUaMGBAQBR0AMdQKAE/lZubqxkzZuijjz7Sli1bVFBQ8Jtpo81mk9PpVGxsrBo3bqyOHTtq0KBB6tmzJ2UAv8vlcunDDz/UkiVL9O233yorK6vi+KVfCwoKUmxsrFq2bKkBAwboz3/+s+Li4gykBlDdKJSAH1i/fr1eeeUVrV69WllZWSoqKvrNJCk8PFwNGjRQ586ddfnll2vgwIG8jIEqVVBQUDEB//rrr7Vnzx6VlJSc8HNsNpsiIyPVqFEj9ezZU2PGjFGbNm0MJQZQVSiUgI9ZtGiRXn31VX3zzTfau3fvbyZDdrtd0dHRSk1NVd++ffXnP/9ZjRs3NpQWkDZv3qyZM2dq+fLl+umnn3TkyJHfvJ0eEhKixMREtW/fXjfffLP69+9vKC2Ac0GhBLxYYWGhpk2bpnnz5ikjI0NFRUUn/HhwcLDi4+PVpk0bXXXVVRo+fDhTR/iEwsJCvfbaa1q0aJHS09O1f//+37wQFB4erhYtWmjo0KEaN24c/24DXoxCCXiRjIwMTZ48WZ9++qmys7NP+AJrt9sVHx+vrl276rbbblPfvn0NJgWqnmVZWrp0qaZPn65169Zp//79J0wyg4KCVL9+ffXp00d33XWX0tLSDKYF8EsUSsCg9957Ty+99JK+/vprHTx48ITnHp1Opxo1aqQBAwbo73//uxITEw0mBczIzs7WU089pSVLligrK+uERzxsNptiY2PVoUMH3XLLLRo8eLDBpEBgo1ACNWjNmjV65JFHtHbtWh05cuSEH6tVq5ZatWqlESNG6M9//jNvWQO/w+VyaebMmZo9e7Z++OEHHT58+IQfj4qKUufOnTVp0iT16NHDUEog8FAogWqUn5+vBx54QAsXLlROTk7F+s5msykhIUHdu3fX3/72N3Xr1s1wUsB3rVmzRs8884xWrVqlffv2VUz6bTabEhMTNXDgQD366KOKj483nBTwXxRKoApZlqVXX31Vzz//vDZv3nzCei4iIkIdOnTQfffdx/OPQDVavny5/t//+39av369CgsLKz7udDqVlpamsWPH6tZbb2ULAFQhCiVQSRs3btSkSZO0atUqFRQUVHw8KChITZo00ahRozRx4kQ5nU6DKYHAZFmWnnnmGb3yyivavn37CS+61apVS127dtVDDz2kLl26GEwJ+D4KJXAOFi1apEmTJumHH3444faZOnXqqF+/fnrsscc4+xHwQtnZ2Zo0aZI+/PBD5eXlVazH7Xa7mjdvrvvvv1/Dhg0znBLwPRRK4AzNmjVLTzzxhLZv317xLKTT6VTbtm11zz338IYp4IOWLl2qxx57TF999ZVKS0slHXv2smHDhrrjjjs0btw4VuPAGaBQAidxfFU2bdo0ZWVlVUwyQkND1b17d02dOlWtWrUynBJAVdmxY4fGjx+v5cuXn3CJQFJSkkaPHq1Jkybx6ApwEhRK4BdcLpcefPBBzZo1S7m5uRUfj4iIUN++ffXss88qJSXFYEIANSEvL08TJkzQBx98cMKz0bVr19aQIUP01FNPKTIy0mBCwLtQKBHwLMvSY489pueee0779++v+Hh0dLQGDRqkqVOnKi4uzmBCACYVFhbq3nvv1dtvv33C54hatWrphhtu0L/+9S8mlwh4FEoErCVLlmjChAnKyMioWGfXqVNHw4YN05NPPsm9wQB+w7IsPfLII5o5c6ays7MrPt6gQQM98sgjGjVqlLlwgEEUSgSUrKwsjR49Wp9//rnKysokSeHh4brmmmv0/PPPs8ICcMYsy9Jdd92lV199tWItbrfb1b59e7388stq27at2YBADaJQwu9ZlqWJEyfqtddeq7imzeFwqGPHjpoxYwYv1gCotOzsbP35z3/W8uXLKy40CA0N1aBBgzR9+nRFR0cbTghUL7vpAEB1eeutt9SoUSMFBQXp2Wef1eHDh5WSkqLZs2ervLxca9eupUwCqBLJycn673//q9LSUn366ac6//zzVVpaqrlz5yomJkYJCQl64oknTji3FvAnTCjhVwoKCnT99dfro48+qvjEXatWLY0YMUJTpkzhwXkANeqpp57SlClTtG/fPknHzrhs166d5s6dq6ZNmxpOB1QdCiX8wvLly/XnP/9ZmZmZko6ttHv27KlXXnmFG2sAGFdYWKibb75ZCxYsqDhAvU6dOnr88cc1ZswYw+mAyqNQwmdZlqX7779f06ZN09GjRyVJMTExuv/++zVx4kTD6QDg97333nsaN25cxVviQUFBuvLKK/XGG29wugR8FoUSPic7O1vXXXed1qxZU3EF4vnnn685c+bwViUAn5Gbm6thw4bp888/r/hc1rx5c73xxhvq1KmT4XTA2eGlHPiM+fPnq169eqpfv75WrVqloKAgDRs2TKWlpUpPT6dMAvApiYmJWr58uSzL0kMPPaSoqCht3bpVnTt3Vq1atfTwww+bjgicMSaU8Hp33nmnnnvuuYrnjhISEvTPf/5TI0aMMJwMAKrWunXrNHLkSGVkZEg6dq5lv379tGDBAtbh8GoUSngly7I0evRozZkzR5ZlyWazqWPHjnr77bd5yQaA3ysuLtaIESO0cOFClZeXS5K6du2q999/X/Hx8YbTAb/FyhtexeVy6corr5TT6dTrr78uj8ejq6++WiUlJfryyy8pkwACQlhYmN555x2VlZXpkUceUWhoqNauXauEhAS1bt264kQLwFswoYRXKCgo0ODBg7VixQpJx956vPHGG/Xiiy/K4XAYTgcA5k2fPl133XWXjhw5Iklq3LixFixYwPPj8AoUShiVm5urK664Qhs2bJAkOZ1OjR8/XpMnTzacDAC8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", + "image/png": "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", "text/plain": [ "
" ] @@ -407,9 +369,12 @@ } ], "source": [ - "pos = {node: (jx_graph.nodes[node]['x'], jx_graph.nodes[node]['y']) for node in jx_graph.nodes()}\n", - "node_colors = [jx_graph.nodes[node]['id'] for node in jx_graph.nodes()]\n", - "nx.draw(jx_graph, pos=pos, node_color=node_colors, cmap='viridis', with_labels=True)" + "pos = {node: (jx_comps.nodes[node]['x'], jx_comps.nodes[node]['y']) for node in jx_comps.nodes()}\n", + "nx.draw(jx_comps, pos=pos, node_color=\"r\", with_labels=False)\n", + "\n", + "morph_comps_graph = morph_comps.to_nx()\n", + "pos = {node: (morph_comps_graph.nodes[node]['x'], morph_comps_graph.nodes[node]['y']) for node in morph_comps_graph.nodes()}\n", + "nx.draw(morph_comps_graph, pos=pos, node_color=\"k\", with_labels=False)" ] }, { From f93d75998773b247f7ac89c90fddee5f6fa0b5a0 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Mon, 26 May 2025 10:20:53 +0200 Subject: [PATCH 06/24] wip: commit before change node and edge tracking --- dev.ipynb | 170 +++++++++++++++++------------------------------------- 1 file changed, 53 insertions(+), 117 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index 710c9ba06..855158051 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 1171, + "execution_count": 1257, "metadata": {}, "outputs": [], "source": [ @@ -86,6 +86,18 @@ " edge_attrs = list(self.edge_attrs[0].keys()) if len(self.edge_attrs) > 0 else []\n", " return f\"MorphTree(nodes={n_nodes}*{node_attrs}, edges={n_edges}*{edge_attrs})\"\n", " \n", + " def node(self, i: int) -> Dict[str, Any]:\n", + " node_idx = jnp.where(self.nodes == i)[0]\n", + " if len(node_idx) > 0:\n", + " return self.node_attrs[node_idx[0]]\n", + " raise ValueError(f\"Node ({i}) does not exist.\")\n", + " \n", + " def edge(self, i: int, j: int) -> Dict[str, Any]:\n", + " edge_idx = jnp.where(jnp.all(self.edges == jnp.array([i, j]), axis=1))[0]\n", + " if len(edge_idx) > 0:\n", + " return self.edge_attrs[edge_idx[0]]\n", + " raise ValueError(f\"Edge ({i}, {j}) does not exist.\")\n", + " \n", " def to_nx(self) -> nx.DiGraph:\n", " G = nx.DiGraph()\n", " node_map = map(int, self.nodes)\n", @@ -274,6 +286,7 @@ " branch_edges.append(list(zip(comp_attrs[:-1, 0], comp_attrs[1:, 0])))\n", " branch_nodes.append(comp_attrs)\n", "\n", + " # TODO: add missing attrs, cell_index, axial_resistvity, membrane_capacitance, voltage\n", " branch_nodes = jnp.concatenate(branch_nodes)\n", " comp_attrs_keys = [\"idx\", \"branch\", \"type\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", @@ -287,7 +300,7 @@ " comps = jnp.array(comp_df.index)\n", " comp_attrs = comp_df.to_dict(orient=\"records\")\n", " comp_edges = jnp.array(sum(branch_edges, []))\n", - " comp_edge_attrs = [{\"type\": -1} for _ in comp_edges]\n", + " comp_edge_attrs = [{\"comp_edge\": True, \"synapse\": False} for _ in comp_edges]\n", "\n", " comp_tree = MorphTree(comps, comp_edges, comp_attrs, comp_edge_attrs)\n", " comp_tree = comp_tree.reindex_nodes(jnp.arange(len(comps)))\n", @@ -296,14 +309,15 @@ }, { "cell_type": "code", - "execution_count": 1172, + "execution_count": 1334, "metadata": {}, "outputs": [], "source": [ "class DummyChannel:\n", - " def __init__(self):\n", - " self.params = {\"gbar\": 1.0, \"e\": 0.0, \"nn_weights\": jnp.ones((10, 10))}\n", - " self.states = {\"m\": 0.5, \"h\": 0.5}\n", + " def __init__(self, name = None):\n", + " self.name = self.__class__.__name__ if name is None else name\n", + " self.params = {f\"gbar_{self.name}\": 1.0, f\"e_{self.name}\": 0.0, f\"nn_weights_{self.name}\": jnp.ones((10, 10))}\n", + " self.states = {f\"m_{self.name}\": 0.5, f\"h_{self.name}\": 0.5}\n", "\n", "def dummy_insert(tree, inds, channel):\n", " # TODO: Should Module and MorphTree be separate or the same thing?\n", @@ -322,12 +336,39 @@ " for key in nodes_df.columns:\n", " values = jnp.array(nodes_df.loc[~nodes_df[key].isna(), key].to_list())\n", " jax_nodes[key] = values\n", - " return jax_nodes" + " return jax_nodes\n", + "\n", + "class DummySynapse:\n", + " def __init__(self, name = None):\n", + " self.name = self.__class__.__name__ if name is None else name\n", + " self.params = {f\"gbar_{self.name}\": 1.0, f\"e_{self.name}\": 0.0, f\"nn_weights_{self.name}\": jnp.ones((10, 10))}\n", + " self.states = {f\"m_{self.name}\": 0.5, f\"h_{self.name}\": 0.5}\n", + "\n", + "def dummy_connect(tree, pre, post, synapse):\n", + " synapse_edges = jnp.vstack([pre, post]).T\n", + " synapse_idxs = np.where((tree.edges[:, :, None] == synapse_edges).all(axis=1).any(axis=1))[0]\n", + " # TODO: map / vectorize this\n", + " for i in synapse_idxs:\n", + " tree.edge_attrs[i][\"synapse\"] = True\n", + " tree.edge_attrs[i].update(synapse.params)\n", + " tree.edge_attrs[i].update(synapse.states)\n", + "\n", + "# There can only be one edge per pair of nodes. (or use MultiDiGraph).\n", + "# This means all synapses need to live in the same edge (i,j)\n", + "# -> treat synapses more like channels, i.e. multiple channels per row in nodes -> multiple synapses per edge.\n", + "# downside cannot connect i and j with the same synapse twice, but can do if one synapse is named differently.\n", + "# think about how to handle if i,j is a comp_edge and also connects via synapses\n", + "\n", + "\n", + "# TODO: node and edge attrs as list or dict?\n", + "# - pro: one can change node / edge idx without changing touching attrs, since pos of node_idx -> pos node_attr\n", + "# - con: hard to index into node / edge attrs\n", + " " ] }, { "cell_type": "code", - "execution_count": 1185, + "execution_count": 1335, "metadata": {}, "outputs": [], "source": [ @@ -354,117 +395,12 @@ }, { "cell_type": "code", - "execution_count": 1186, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "pos = {node: (jx_comps.nodes[node]['x'], jx_comps.nodes[node]['y']) for node in jx_comps.nodes()}\n", - "nx.draw(jx_comps, pos=pos, node_color=\"r\", with_labels=False)\n", - "\n", - "morph_comps_graph = morph_comps.to_nx()\n", - "pos = {node: (morph_comps_graph.nodes[node]['x'], morph_comps_graph.nodes[node]['y']) for node in morph_comps_graph.nodes()}\n", - "nx.draw(morph_comps_graph, pos=pos, node_color=\"k\", with_labels=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 981, + "execution_count": 1336, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
branchtypeidxyzrl
10113.01.50.00.00.325
31112.00.00.00.01.000
52114.00.02.00.00.300
\n", - "
" - ], - "text/plain": [ - " branch type id x y z r l\n", - "1 0 1 1 3.0 1.5 0.0 0.0 0.325\n", - "3 1 1 1 2.0 0.0 0.0 0.0 1.000\n", - "5 2 1 1 4.0 0.0 2.0 0.0 0.300" - ] - }, - "execution_count": 981, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "morph_comps.to_pandas()[0].loc[morph_comps.to_pandas()[0]['type'] == 1]" + "dummy_connect(morph_comps, jnp.array([0, 1]), jnp.array([2, 3]), DummySynapse(\"test1\"))\n", + "dummy_connect(morph_comps, jnp.array([0, 1]), jnp.array([2, 3]), DummySynapse(\"test2\"))" ] }, { From 168ce4e0aed819d59fb145161f61cf192851e01a Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Mon, 26 May 2025 11:35:32 +0200 Subject: [PATCH 07/24] fix: nodes and edges are dicts now --- dev.ipynb | 155 ++++++++++++++++++++++++------------------------------ 1 file changed, 70 insertions(+), 85 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index 855158051..d2967fc4a 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -48,86 +48,76 @@ }, { "cell_type": "code", - "execution_count": 1257, + "execution_count": 1575, "metadata": {}, "outputs": [], "source": [ "def swc_to_morph_tree(fname: str, num_lines: Optional[int] = None) -> MorphTree:\n", - " i_id_xyzr_p = jnp.array(np.loadtxt(fname)[:num_lines])\n", + " i_id_xyzr_p = np.loadtxt(fname)[:num_lines]\n", " \n", - " edges = i_id_xyzr_p[:, [0, -1]]\n", - " edges = edges[edges[:, 1] != -1].astype(int)\n", + " node_attrs, edge_attrs = {}, {}\n", + " for i, id, x, y, z, r, j in i_id_xyzr_p:\n", + " node_attrs[int(i)] = {\"id\": int(id), \"x\": float(x), \"y\": float(y), \"z\": float(z), \"r\": float(r)}\n", + " if j != -1:\n", + " edge_attrs[int(j), int(i)] = {}\n", " \n", - " nodes = i_id_xyzr_p[:, 0].astype(int)\n", - " \n", - " get_node_attrs = lambda id, x, y, z, r: {\"id\": int(id), \"x\": x, \"y\": y, \"z\": z, \"r\": r}\n", - " node_attrs = list(map(get_node_attrs, *i_id_xyzr_p[:, 1:-1].T)) \n", - " return MorphTree(nodes, edges, node_attrs)\n", + " return MorphTree(node_attrs, edge_attrs)\n", "\n", "@dataclass\n", "class MorphTree:\n", - " nodes: jnp.ndarray\n", - " edges: jnp.ndarray\n", - " node_attrs: List[Dict[str, Any]] = None\n", - " edge_attrs: List[Dict[str, Any]] = None\n", + " node_attrs: Dict[int, Dict[str, Any]]\n", + " edge_attrs: Dict[Tuple[int, int], Dict[str, Any]]\n", " global_attrs: Dict[str, Any] = field(default_factory=dict)\n", "\n", - " def __post_init__(self) -> None:\n", - " if self.node_attrs is None:\n", - " self.node_attrs = [{}]*len(self.nodes)\n", - " if self.edge_attrs is None:\n", - " self.edge_attrs = [{}]*len(self.edges)\n", + " @property\n", + " def nodes(self) -> jnp.ndarray:\n", + " return jnp.array(list(self.node_attrs.keys())).astype(int)\n", + "\n", + " @property\n", + " def edges(self) -> jnp.ndarray:\n", + " return jnp.array(list(self.edge_attrs.keys())).astype(int)\n", "\n", " def __repr__(self) -> str:\n", - " n_nodes = len(self.nodes)\n", - " n_edges = len(self.edges)\n", + " n_nodes = len(self.node_attrs)\n", + " n_edges = len(self.edge_attrs)\n", "\n", - " node_attrs = list(self.node_attrs[0].keys()) if len(self.node_attrs) > 0 else []\n", - " edge_attrs = list(self.edge_attrs[0].keys()) if len(self.edge_attrs) > 0 else []\n", + " node_keys = list(next(iter(self.node_attrs.values())).keys())\n", + " edge_keys = list(next(iter(self.edge_attrs.values())).keys())\n", + "\n", + " node_attrs = node_keys if len(self.node_attrs) > 0 else []\n", + " edge_attrs = edge_keys if len(self.edge_attrs) > 0 else []\n", " return f\"MorphTree(nodes={n_nodes}*{node_attrs}, edges={n_edges}*{edge_attrs})\"\n", " \n", " def node(self, i: int) -> Dict[str, Any]:\n", - " node_idx = jnp.where(self.nodes == i)[0]\n", - " if len(node_idx) > 0:\n", - " return self.node_attrs[node_idx[0]]\n", - " raise ValueError(f\"Node ({i}) does not exist.\")\n", + " return self.node_attrs[i]\n", " \n", " def edge(self, i: int, j: int) -> Dict[str, Any]:\n", - " edge_idx = jnp.where(jnp.all(self.edges == jnp.array([i, j]), axis=1))[0]\n", - " if len(edge_idx) > 0:\n", - " return self.edge_attrs[edge_idx[0]]\n", - " raise ValueError(f\"Edge ({i}, {j}) does not exist.\")\n", + " return self.edge_attrs[i, j]\n", " \n", " def to_nx(self) -> nx.DiGraph:\n", " G = nx.DiGraph()\n", - " node_map = map(int, self.nodes)\n", - " edge_map = map(lambda x: tuple(map(int, x)), self.edges.T)\n", - " G.add_nodes_from(zip(node_map, self.node_attrs))\n", - " G.add_edges_from(zip(*edge_map, self.edge_attrs))\n", + " G.add_nodes_from(self.node_attrs.items())\n", + " G.add_edges_from((i, j, d) for (i, j), d in self.edge_attrs.items())\n", " return G\n", " \n", " @staticmethod\n", " def from_nx(G: nx.DiGraph) -> MorphTree:\n", - " nodes = jnp.array(list(G.nodes))\n", - " edges = jnp.array(list(G.edges))\n", - " node_attrs = [G.nodes[n] for n in G.nodes]\n", - " edge_attrs = [G.edges[e] for e in G.edges]\n", - " return MorphTree(nodes, edges, node_attrs, edge_attrs)\n", + " node_attrs = {n: G.nodes[n] for n in G.nodes}\n", + " edge_attrs = {(i, j): G.edges[i, j] for i, j in G.edges}\n", + " return MorphTree(node_attrs, edge_attrs)\n", " \n", " def to_pandas(self) -> Tuple[pd.DataFrame, pd.DataFrame]:\n", - " node_df = pd.DataFrame(self.node_attrs, index=np.array(self.nodes))\n", - " edge_df = pd.DataFrame(self.edge_attrs)\n", + " node_df = pd.DataFrame(self.node_attrs.values(), index=self.node_attrs.keys())\n", + " edge_df = pd.DataFrame(self.edge_attrs.values(), index=self.edge_attrs.keys())\n", " edge_index = pd.MultiIndex.from_arrays(np.array(self.edges).T)\n", " edge_df = edge_df.set_index(edge_index)\n", " return node_df, edge_df\n", " \n", " @staticmethod\n", " def from_pandas(node_df: pd.DataFrame, edge_df: pd.DataFrame) -> MorphTree:\n", - " node_attrs = node_df.to_dict(orient=\"records\")\n", - " edge_attrs = edge_df.to_dict(orient=\"records\")\n", - " edges = edge_df.index.to_numpy()\n", - " nodes = node_df.index.to_numpy()\n", - " return MorphTree(nodes, edges, node_attrs, edge_attrs)\n", + " node_attrs = node_df.to_dict(orient=\"index\")\n", + " edge_attrs = edge_df.to_dict(orient=\"index\")\n", + " return MorphTree(node_attrs, edge_attrs)\n", " \n", " def plot(self, **kwargs: Any) -> None:\n", " G = self.to_nx()\n", @@ -138,28 +128,25 @@ " nx.draw(G, pos, with_labels=True, **kwargs)\n", " plt.show()\n", "\n", - " def reindex_nodes(self, new_indices: jnp.ndarray) -> MorphTree:\n", - " def remap(x: int) -> int:\n", - " idx = jnp.argmax(self.nodes == x)\n", - " exists = self.nodes[idx] == x\n", - " return jnp.where(exists, new_indices[idx], x)\n", - "\n", - " new_nodes = vmap(remap)(self.nodes.ravel()).reshape(self.nodes.shape)\n", - " new_edges = vmap(remap)(self.edges.ravel()).reshape(self.edges.shape)\n", - " return MorphTree(new_nodes, new_edges, self.node_attrs, self.edge_attrs)\n", + " def reindex_nodes(self, mapping: dict) -> MorphTree:\n", + " new_node_attrs = {mapping[i]: attrs for i, attrs in self.node_attrs.items()}\n", + " \n", + " new_edge_attrs = {}\n", + " for (i, j), attrs in self.edge_attrs.items():\n", + " new_edge_attrs[(mapping[i], mapping[j])] = attrs\n", + " \n", + " return MorphTree(new_node_attrs, new_edge_attrs)\n", " \n", - " def reorder_tree(self, new_order: jnp.ndarray) -> MorphTree:\n", - " # TODO: check this does what I think it does, i.e. change the edge orientation\n", - " # in order of appearance of the nodes in self.nodes.\n", - " new_nodes = self.nodes[new_order]\n", - " new_tree = self.reindex_nodes(new_nodes)\n", - "\n", - " new_edges = new_tree.edges\n", - " idx_i = jnp.where(new_edges[:,0] == new_tree.nodes[:, None])[0]\n", - " idx_j = jnp.where(new_edges[:,1] == new_tree.nodes[:, None])[0]\n", - " is_descending = ~(idx_i < idx_j)[:, None]\n", - " ascending_edges = jnp.where(is_descending, new_edges[:, ::-1], new_edges)\n", - " return MorphTree(new_nodes, ascending_edges, new_tree.node_attrs, new_tree.edge_attrs)\n", + " # def reorder_tree(self, new_order: jnp.ndarray) -> MorphTree:\n", + " # # TODO: check this does what I think it does, i.e. change the edge orientation\n", + " # # in order of appearance of the nodes in self.nodes.\n", + " # edges = self.edges\n", + " # idx_i = jnp.where(edges[:,0] == new_order[:, None])[0]\n", + " # idx_j = jnp.where(edges[:,1] == new_order[:, None])[0]\n", + " # is_descending = ~(idx_i < idx_j)\n", + " # for (i,j) in edges[is_descending]:\n", + " # self.edge_attrs[int(j), int(i)] = self.edge_attrs.pop((int(i), int(j)))\n", + " # return self\n", "\n", "def list_branches(tree: MorphTree, return_branchpoints: bool = False) -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", " G = tree.to_nx().to_undirected()\n", @@ -297,19 +284,19 @@ " comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", " comp_df = comp_df.set_index(\"idx\")\n", "\n", - " comps = jnp.array(comp_df.index)\n", - " comp_attrs = comp_df.to_dict(orient=\"records\")\n", - " comp_edges = jnp.array(sum(branch_edges, []))\n", - " comp_edge_attrs = [{\"comp_edge\": True, \"synapse\": False} for _ in comp_edges]\n", + " \n", + " comp_attrs = comp_df.to_dict(orient=\"index\")\n", + " comp_edges = sum(branch_edges, [])\n", + " comp_edge_attrs = {(i,j): {\"comp_edge\": True, \"synapse\": False} for i,j in comp_edges}\n", "\n", - " comp_tree = MorphTree(comps, comp_edges, comp_attrs, comp_edge_attrs)\n", - " comp_tree = comp_tree.reindex_nodes(jnp.arange(len(comps)))\n", + " comp_tree = MorphTree(comp_attrs, comp_edge_attrs)\n", + " comp_tree = comp_tree.reindex_nodes(dict(zip(comp_df.index, range(len(comp_df)))))\n", " return comp_tree" ] }, { "cell_type": "code", - "execution_count": 1334, + "execution_count": 1576, "metadata": {}, "outputs": [], "source": [ @@ -345,13 +332,11 @@ " self.states = {f\"m_{self.name}\": 0.5, f\"h_{self.name}\": 0.5}\n", "\n", "def dummy_connect(tree, pre, post, synapse):\n", - " synapse_edges = jnp.vstack([pre, post]).T\n", - " synapse_idxs = np.where((tree.edges[:, :, None] == synapse_edges).all(axis=1).any(axis=1))[0]\n", " # TODO: map / vectorize this\n", - " for i in synapse_idxs:\n", - " tree.edge_attrs[i][\"synapse\"] = True\n", - " tree.edge_attrs[i].update(synapse.params)\n", - " tree.edge_attrs[i].update(synapse.states)\n", + " for i, j in zip(pre, post):\n", + " tree.edge_attrs[i, j][\"synapse\"] = True\n", + " tree.edge_attrs[i, j].update(synapse.params)\n", + " tree.edge_attrs[i, j].update(synapse.states)\n", "\n", "# There can only be one edge per pair of nodes. (or use MultiDiGraph).\n", "# This means all synapses need to live in the same edge (i,j)\n", @@ -368,7 +353,7 @@ }, { "cell_type": "code", - "execution_count": 1335, + "execution_count": 1577, "metadata": {}, "outputs": [], "source": [ @@ -395,17 +380,17 @@ }, { "cell_type": "code", - "execution_count": 1336, + "execution_count": 1573, "metadata": {}, "outputs": [], "source": [ - "dummy_connect(morph_comps, jnp.array([0, 1]), jnp.array([2, 3]), DummySynapse(\"test1\"))\n", - "dummy_connect(morph_comps, jnp.array([0, 1]), jnp.array([2, 3]), DummySynapse(\"test2\"))" + "dummy_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test1\"))\n", + "dummy_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test2\"))" ] }, { "cell_type": "code", - "execution_count": 877, + "execution_count": 1582, "metadata": {}, "outputs": [ { From 8c70442aa039e50f0656d3a5f88cfa6736d4a2b1 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Mon, 26 May 2025 13:20:04 +0200 Subject: [PATCH 08/24] wip: save wip --- dev.ipynb | 374 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 339 insertions(+), 35 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index d2967fc4a..b615a34ea 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 1575, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -63,6 +63,7 @@ " \n", " return MorphTree(node_attrs, edge_attrs)\n", "\n", + "@jax.tree_util.register_dataclass\n", "@dataclass\n", "class MorphTree:\n", " node_attrs: Dict[int, Dict[str, Any]]\n", @@ -137,16 +138,17 @@ " \n", " return MorphTree(new_node_attrs, new_edge_attrs)\n", " \n", - " # def reorder_tree(self, new_order: jnp.ndarray) -> MorphTree:\n", - " # # TODO: check this does what I think it does, i.e. change the edge orientation\n", - " # # in order of appearance of the nodes in self.nodes.\n", - " # edges = self.edges\n", - " # idx_i = jnp.where(edges[:,0] == new_order[:, None])[0]\n", - " # idx_j = jnp.where(edges[:,1] == new_order[:, None])[0]\n", - " # is_descending = ~(idx_i < idx_j)\n", - " # for (i,j) in edges[is_descending]:\n", - " # self.edge_attrs[int(j), int(i)] = self.edge_attrs.pop((int(i), int(j)))\n", - " # return self\n", + " def reorder_tree(self, new_order: np.ndarray) -> MorphTree:\n", + " # TODO: check this does what I think it does, i.e. change the edge orientation\n", + " # in order of appearance of the nodes in self.nodes.\n", + " edges = np.array(self.edges)\n", + " idx_i = np.where(edges[:,0] == new_order[:, None])[0]\n", + " idx_j = np.where(edges[:,1] == new_order[:, None])[0]\n", + " is_descending = ~(idx_i < idx_j)\n", + " for (i,j) in edges[is_descending]:\n", + " print(i,j)\n", + " self.edge_attrs[j, i] = self.edge_attrs.pop((i, j))\n", + " return self\n", "\n", "def list_branches(tree: MorphTree, return_branchpoints: bool = False) -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", " G = tree.to_nx().to_undirected()\n", @@ -248,10 +250,10 @@ " comp_locs = list(np.linspace(comp_len/2, branch_len - comp_len/2, num_comps))\n", " \n", " # Create node indices and attributes\n", - " # branch_inds, comp_type, comp_id, comp_len\n", + " # branch_inds, branchpoint, comp_id, comp_len\n", " branch_tips = branch[0], branch[-1]\n", - " branch_tip_attrs = [i, -1, -1, 0]\n", - " comp_attrs = [i, 0, branch_id, comp_len] # comp_type: -1: branchpoint, 0: compartment\n", + " branch_tip_attrs = [i, True, -1, 0]\n", + " comp_attrs = [i, False, branch_id, comp_len]\n", "\n", " comp_inds = proposed_comp_inds[i*num_comps:(i+1)*num_comps]\n", " comp_inds = np.array([branch_tips[0], *comp_inds, branch_tips[1]])\n", @@ -275,10 +277,12 @@ "\n", " # TODO: add missing attrs, cell_index, axial_resistvity, membrane_capacitance, voltage\n", " branch_nodes = jnp.concatenate(branch_nodes)\n", - " comp_attrs_keys = [\"idx\", \"branch\", \"type\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", + " comp_attrs_keys = [\"idx\", \"branch\", \"branchpoint\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", - " int_cols = [\"idx\", \"branch\", \"type\", \"id\"]\n", + " int_cols = [\"idx\", \"branch\", \"id\"]\n", + " bool_cols = [\"branchpoint\"]\n", " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", + " comp_df[bool_cols] = comp_df[bool_cols].astype(bool)\n", " \n", " # drop duplicated branch nodes\n", " comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", @@ -296,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": 1576, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -306,24 +310,37 @@ " self.params = {f\"gbar_{self.name}\": 1.0, f\"e_{self.name}\": 0.0, f\"nn_weights_{self.name}\": jnp.ones((10, 10))}\n", " self.states = {f\"m_{self.name}\": 0.5, f\"h_{self.name}\": 0.5}\n", "\n", - "def dummy_insert(tree, inds, channel):\n", + "def tree_insert(tree, inds, channel):\n", " # TODO: Should Module and MorphTree be separate or the same thing?\n", + " tree.global_attrs[\"channels\"][channel.name] = channel\n", " for i in inds:\n", " tree.node_attrs[i].update(channel.params)\n", " tree.node_attrs[i].update(channel.states)\n", - " tree.global_attrs[\"channels\"].append(channel)\n", "\n", - "def dummy_set(tree, inds, key, value):\n", - " for i in inds:\n", - " tree.node_attrs[i][key] = value\n", + "def tree_set(tree, inds, key, value):\n", + " if isinstance(inds[0], tuple):\n", + " for i, j in inds:\n", + " tree.edge_attrs[(i,j)][key] = value\n", + " else:\n", + " for i in inds:\n", + " tree.node_attrs[i][key] = value\n", "\n", - "def dummy_to_pytree(tree):\n", - " nodes_df = tree.to_pandas()[0]\n", - " jax_nodes = {}\n", - " for key in nodes_df.columns:\n", - " values = jnp.array(nodes_df.loc[~nodes_df[key].isna(), key].to_list())\n", + "def tree_to_pytree(tree):\n", + " nodes_df, edge_df = tree.to_pandas()\n", + " jax_nodes, jax_edges = {}, {}\n", + " \n", + " node_data = nodes_df.loc[~nodes_df.branchpoint]\n", + " node_data = node_data.drop(columns=[\"branch\", \"branchpoint\", \"id\"])\n", + " for key in node_data.columns:\n", + " values = jnp.array(node_data.loc[~node_data[key].isna(), key].to_list())\n", " jax_nodes[key] = values\n", - " return jax_nodes\n", + "\n", + " edge_data = edge_df.loc[edge_df.synapse]\n", + " edge_data = edge_data.drop(columns=[\"comp_edge\", \"synapse\"])\n", + " for key in edge_data.columns:\n", + " values = jnp.array(edge_data.loc[~edge_data[key].isna(), key].to_list())\n", + " jax_edges[key] = values\n", + " return jax_nodes, jax_edges\n", "\n", "class DummySynapse:\n", " def __init__(self, name = None):\n", @@ -331,20 +348,23 @@ " self.params = {f\"gbar_{self.name}\": 1.0, f\"e_{self.name}\": 0.0, f\"nn_weights_{self.name}\": jnp.ones((10, 10))}\n", " self.states = {f\"m_{self.name}\": 0.5, f\"h_{self.name}\": 0.5}\n", "\n", - "def dummy_connect(tree, pre, post, synapse):\n", + "def tree_connect(tree, pre, post, synapse):\n", " # TODO: map / vectorize this\n", + " tree.global_attrs[\"synapses\"][synapse.name] = synapse\n", " for i, j in zip(pre, post):\n", + " if (i,j) not in tree.edge_attrs:\n", + " tree.edge_attrs[(i,j)] = {\"comp_edge\": False}\n", " tree.edge_attrs[i, j][\"synapse\"] = True\n", " tree.edge_attrs[i, j].update(synapse.params)\n", " tree.edge_attrs[i, j].update(synapse.states)\n", "\n", + "\n", "# There can only be one edge per pair of nodes. (or use MultiDiGraph).\n", "# This means all synapses need to live in the same edge (i,j)\n", "# -> treat synapses more like channels, i.e. multiple channels per row in nodes -> multiple synapses per edge.\n", "# downside cannot connect i and j with the same synapse twice, but can do if one synapse is named differently.\n", "# think about how to handle if i,j is a comp_edge and also connects via synapses\n", "\n", - "\n", "# TODO: node and edge attrs as list or dict?\n", "# - pro: one can change node / edge idx without changing touching attrs, since pos of node_idx -> pos node_attr\n", "# - con: hard to index into node / edge attrs\n", @@ -353,7 +373,7 @@ }, { "cell_type": "code", - "execution_count": 1577, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -372,7 +392,7 @@ "\"morph_allen_485574832.swc\",\n", "]\n", "\n", - "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[-3])\n", + "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[3])\n", "\n", "morph_comps = compartmentalize(MorphTree.from_nx(jx_graph.copy()), num_comps=1)\n", "jx_comps = build_compartment_graph(jx_graph, ncomp=1)" @@ -380,14 +400,298 @@ }, { "cell_type": "code", - "execution_count": 1573, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ - "dummy_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test1\"))\n", - "dummy_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test2\"))" + "morph_comps.global_attrs[\"channels\"] = {}\n", + "morph_comps.global_attrs[\"synapses\"] = {}\n", + "\n", + "\n", + "tree_insert(morph_comps, [0, 1], DummyChannel(\"test1\"))\n", + "tree_insert(morph_comps, [0, 1], DummyChannel(\"test2\"))\n", + "\n", + "tree_connect(morph_comps, [0, 1], [3, 2], DummySynapse(\"test1\"))\n", + "tree_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test2\"))\n", + "\n", + "tree_set(morph_comps, [0, 1], \"gbar_test1\", 123)\n", + "tree_set(morph_comps, [(0, 1)], \"gbar_test2\", 123)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
comp_edgesynapsegbar_test2e_test2nn_weights_test2m_test2h_test2gbar_test1e_test1nn_weights_test1m_test1h_test1
01TrueTrue123.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.5NaNNaNNaNNaNNaN
12TrueTrue1.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.51.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.5
23TrueFalseNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
34TrueFalseNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
03FalseTrueNaNNaNNaNNaNNaN1.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.5
\n", + "
" + ], + "text/plain": [ + " comp_edge synapse gbar_test2 e_test2 \\\n", + "0 1 True True 123.0 0.0 \n", + "1 2 True True 1.0 0.0 \n", + "2 3 True False NaN NaN \n", + "3 4 True False NaN NaN \n", + "0 3 False True NaN NaN \n", + "\n", + " nn_weights_test2 m_test2 h_test2 \\\n", + "0 1 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", + "1 2 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", + "2 3 NaN NaN NaN \n", + "3 4 NaN NaN NaN \n", + "0 3 NaN NaN NaN \n", + "\n", + " gbar_test1 e_test1 nn_weights_test1 \\\n", + "0 1 NaN NaN NaN \n", + "1 2 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", + "2 3 NaN NaN NaN \n", + "3 4 NaN NaN NaN \n", + "0 3 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", + "\n", + " m_test1 h_test1 \n", + "0 1 NaN NaN \n", + "1 2 0.5 0.5 \n", + "2 3 NaN NaN \n", + "3 4 NaN NaN \n", + "0 3 0.5 0.5 " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "morph_comps.to_pandas()[1]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "({'l': Array([2.2, 1. , 2.6], dtype=float64),\n", + " 'x': Array([2.1, 0.5, 0. ], dtype=float64),\n", + " 'y': Array([0. , 0. , 1.3], dtype=float64),\n", + " 'z': Array([0., 0., 0.], dtype=float64),\n", + " 'r': Array([1., 1., 1.], dtype=float64),\n", + " 'gbar_test1': Array([123.], dtype=float64),\n", + " 'e_test1': Array([0.], dtype=float64),\n", + " 'nn_weights_test1': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", + " 'm_test1': Array([0.5], dtype=float64),\n", + " 'h_test1': Array([0.5], dtype=float64),\n", + " 'gbar_test2': Array([1.], dtype=float64),\n", + " 'e_test2': Array([0.], dtype=float64),\n", + " 'nn_weights_test2': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", + " 'm_test2': Array([0.5], dtype=float64),\n", + " 'h_test2': Array([0.5], dtype=float64)},\n", + " {'gbar_test2': Array([123., 1.], dtype=float64),\n", + " 'e_test2': Array([0., 0.], dtype=float64),\n", + " 'nn_weights_test2': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]],\n", + " \n", + " [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", + " 'm_test2': Array([0.5, 0.5], dtype=float64),\n", + " 'h_test2': Array([0.5, 0.5], dtype=float64),\n", + " 'gbar_test1': Array([1., 1.], dtype=float64),\n", + " 'e_test1': Array([0., 0.], dtype=float64),\n", + " 'nn_weights_test1': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]],\n", + " \n", + " [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", + " 'm_test1': Array([0.5, 0.5], dtype=float64),\n", + " 'h_test1': Array([0.5, 0.5], dtype=float64)})" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tree_to_pytree(morph_comps)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": 1582, From 0c632cbe6e211496737dd0dba175ed767bf3573a Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Mon, 26 May 2025 13:50:14 +0200 Subject: [PATCH 09/24] wip: save wip --- dev.ipynb | 239 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 150 insertions(+), 89 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index b615a34ea..0a59a2ba1 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -252,12 +252,13 @@ " # Create node indices and attributes\n", " # branch_inds, branchpoint, comp_id, comp_len\n", " branch_tips = branch[0], branch[-1]\n", - " branch_tip_attrs = [i, True, -1, 0]\n", - " comp_attrs = [i, False, branch_id, comp_len]\n", + " branch_tip_attrs = [[i, True, node_attrs[\"id\"].iloc[0], 0],\n", + " [i, True, node_attrs[\"id\"].iloc[-1], 0]]\n", + " comp_attrs = [i, False, branch_id, comp_len]*num_comps\n", "\n", " comp_inds = proposed_comp_inds[i*num_comps:(i+1)*num_comps]\n", " comp_inds = np.array([branch_tips[0], *comp_inds, branch_tips[1]])\n", - " comp_attrs = np.array([branch_tip_attrs] + [comp_attrs]*num_comps + [branch_tip_attrs])\n", + " comp_attrs = [branch_tip_attrs[0]] + [comp_attrs] + [branch_tip_attrs[1]]\n", " comp_attrs = np.hstack([comp_inds[:, None], comp_attrs])\n", " \n", " # Interpolate xyzr coordinates and combine with attributes\n", @@ -295,12 +296,16 @@ "\n", " comp_tree = MorphTree(comp_attrs, comp_edge_attrs)\n", " comp_tree = comp_tree.reindex_nodes(dict(zip(comp_df.index, range(len(comp_df)))))\n", - " return comp_tree" + " return comp_tree\n", + "\n", + "# def set_solve_order(tree: MorphTree, solve_order: List[int]) -> MorphTree:\n", + "# # TODO: do we want to rm branchpoints and comp_edges?\n", + "# return" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -320,10 +325,12 @@ "def tree_set(tree, inds, key, value):\n", " if isinstance(inds[0], tuple):\n", " for i, j in inds:\n", - " tree.edge_attrs[(i,j)][key] = value\n", + " if key in tree.edge_attrs[(i,j)]:\n", + " tree.edge_attrs[(i,j)][key] = value\n", " else:\n", " for i in inds:\n", - " tree.node_attrs[i][key] = value\n", + " if key in tree.node_attrs[i]:\n", + " tree.node_attrs[i][key] = value\n", "\n", "def tree_to_pytree(tree):\n", " nodes_df, edge_df = tree.to_pandas()\n", @@ -368,12 +375,14 @@ "# TODO: node and edge attrs as list or dict?\n", "# - pro: one can change node / edge idx without changing touching attrs, since pos of node_idx -> pos node_attr\n", "# - con: hard to index into node / edge attrs\n", + "\n", + "# TODO: get rid of xyzr in most usecases and use the comp / node xyzrs!? -> simplifies all plotting to networkx!\n", " " ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -392,15 +401,15 @@ "\"morph_allen_485574832.swc\",\n", "]\n", "\n", - "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[3])\n", + "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[-3])\n", "\n", "morph_comps = compartmentalize(MorphTree.from_nx(jx_graph.copy()), num_comps=1)\n", - "jx_comps = build_compartment_graph(jx_graph, ncomp=1)" + "# jx_comps = build_compartment_graph(jx_graph, ncomp=1)" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 103, "metadata": {}, "outputs": [], "source": [ @@ -408,19 +417,19 @@ "morph_comps.global_attrs[\"synapses\"] = {}\n", "\n", "\n", - "tree_insert(morph_comps, [0, 1], DummyChannel(\"test1\"))\n", - "tree_insert(morph_comps, [0, 1], DummyChannel(\"test2\"))\n", + "tree_insert(morph_comps, [0, 2], DummyChannel(\"test1\"))\n", + "tree_insert(morph_comps, [0, 2], DummyChannel(\"test2\"))\n", "\n", "tree_connect(morph_comps, [0, 1], [3, 2], DummySynapse(\"test1\"))\n", "tree_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test2\"))\n", "\n", - "tree_set(morph_comps, [0, 1], \"gbar_test1\", 123)\n", + "tree_set(morph_comps, [0, 2], \"gbar_test1\", 123)\n", "tree_set(morph_comps, [(0, 1)], \"gbar_test2\", 123)" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 104, "metadata": {}, "outputs": [ { @@ -444,32 +453,63 @@ " \n", " \n", " \n", - " \n", - " comp_edge\n", - " synapse\n", - " gbar_test2\n", - " e_test2\n", - " nn_weights_test2\n", - " m_test2\n", - " h_test2\n", + " branch\n", + " branchpoint\n", + " id\n", + " l\n", + " x\n", + " y\n", + " z\n", + " r\n", " gbar_test1\n", " e_test1\n", " nn_weights_test1\n", " m_test1\n", " h_test1\n", + " gbar_test2\n", + " e_test2\n", + " nn_weights_test2\n", + " m_test2\n", + " h_test2\n", " \n", " \n", " \n", " \n", " 0\n", - " 1\n", - " True\n", - " True\n", + " 0\n", + " False\n", + " 1\n", + " 2.2\n", + " 2.1\n", + " 0.0\n", + " 0.0\n", + " 1.0\n", " 123.0\n", " 0.0\n", " [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", " 0.5\n", " 0.5\n", + " 1.0\n", + " 0.0\n", + " [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", + " 0.5\n", + " 0.5\n", + " \n", + " \n", + " 1\n", + " 0\n", + " True\n", + " 1\n", + " 0.0\n", + " 1.0\n", + " 0.0\n", + " 0.0\n", + " 1.0\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", " NaN\n", " NaN\n", " NaN\n", @@ -477,11 +517,16 @@ " NaN\n", " \n", " \n", - " 1\n", " 2\n", - " True\n", - " True\n", + " 1\n", + " False\n", + " 1\n", + " 1.0\n", + " 0.5\n", + " 0.0\n", + " 0.0\n", " 1.0\n", + " 123.0\n", " 0.0\n", " [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", " 0.5\n", @@ -493,10 +538,15 @@ " 0.5\n", " \n", " \n", - " 2\n", " 3\n", + " 1\n", " True\n", - " False\n", + " 1\n", + " 0.0\n", + " 0.0\n", + " 0.0\n", + " 0.0\n", + " 1.0\n", " NaN\n", " NaN\n", " NaN\n", @@ -509,10 +559,15 @@ " NaN\n", " \n", " \n", - " 3\n", " 4\n", - " True\n", + " 2\n", " False\n", + " 3\n", + " 2.6\n", + " 0.0\n", + " 1.3\n", + " 0.0\n", + " 1.0\n", " NaN\n", " NaN\n", " NaN\n", @@ -524,68 +579,52 @@ " NaN\n", " NaN\n", " \n", - " \n", - " 0\n", - " 3\n", - " False\n", - " True\n", - " NaN\n", - " NaN\n", - " NaN\n", - " NaN\n", - " NaN\n", - " 1.0\n", - " 0.0\n", - " [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", - " 0.5\n", - " 0.5\n", - " \n", " \n", "\n", "" ], "text/plain": [ - " comp_edge synapse gbar_test2 e_test2 \\\n", - "0 1 True True 123.0 0.0 \n", - "1 2 True True 1.0 0.0 \n", - "2 3 True False NaN NaN \n", - "3 4 True False NaN NaN \n", - "0 3 False True NaN NaN \n", + " branch branchpoint id l x y z r gbar_test1 e_test1 \\\n", + "0 0 False 1 2.2 2.1 0.0 0.0 1.0 123.0 0.0 \n", + "1 0 True 1 0.0 1.0 0.0 0.0 1.0 NaN NaN \n", + "2 1 False 1 1.0 0.5 0.0 0.0 1.0 123.0 0.0 \n", + "3 1 True 1 0.0 0.0 0.0 0.0 1.0 NaN NaN \n", + "4 2 False 3 2.6 0.0 1.3 0.0 1.0 NaN NaN \n", "\n", - " nn_weights_test2 m_test2 h_test2 \\\n", - "0 1 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", - "1 2 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", - "2 3 NaN NaN NaN \n", - "3 4 NaN NaN NaN \n", - "0 3 NaN NaN NaN \n", + " nn_weights_test1 m_test1 h_test1 \\\n", + "0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", + "1 NaN NaN NaN \n", + "2 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", + "3 NaN NaN NaN \n", + "4 NaN NaN NaN \n", "\n", - " gbar_test1 e_test1 nn_weights_test1 \\\n", - "0 1 NaN NaN NaN \n", - "1 2 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", - "2 3 NaN NaN NaN \n", - "3 4 NaN NaN NaN \n", - "0 3 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", + " gbar_test2 e_test2 nn_weights_test2 \\\n", + "0 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", + "1 NaN NaN NaN \n", + "2 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", + "3 NaN NaN NaN \n", + "4 NaN NaN NaN \n", "\n", - " m_test1 h_test1 \n", - "0 1 NaN NaN \n", - "1 2 0.5 0.5 \n", - "2 3 NaN NaN \n", - "3 4 NaN NaN \n", - "0 3 0.5 0.5 " + " m_test2 h_test2 \n", + "0 0.5 0.5 \n", + "1 NaN NaN \n", + "2 0.5 0.5 \n", + "3 NaN NaN \n", + "4 NaN NaN " ] }, - "execution_count": 8, + "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "morph_comps.to_pandas()[1]" + "morph_comps.to_pandas()[0]" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 85, "metadata": {}, "outputs": [ { @@ -596,8 +635,8 @@ " 'y': Array([0. , 0. , 1.3], dtype=float64),\n", " 'z': Array([0., 0., 0.], dtype=float64),\n", " 'r': Array([1., 1., 1.], dtype=float64),\n", - " 'gbar_test1': Array([123.], dtype=float64),\n", - " 'e_test1': Array([0.], dtype=float64),\n", + " 'gbar_test1': Array([123., 123.], dtype=float64),\n", + " 'e_test1': Array([0., 0.], dtype=float64),\n", " 'nn_weights_test1': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", @@ -607,11 +646,22 @@ " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]],\n", + " \n", + " [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", - " 'm_test1': Array([0.5], dtype=float64),\n", - " 'h_test1': Array([0.5], dtype=float64),\n", - " 'gbar_test2': Array([1.], dtype=float64),\n", - " 'e_test2': Array([0.], dtype=float64),\n", + " 'm_test1': Array([0.5, 0.5], dtype=float64),\n", + " 'h_test1': Array([0.5, 0.5], dtype=float64),\n", + " 'gbar_test2': Array([1., 1.], dtype=float64),\n", + " 'e_test2': Array([0., 0.], dtype=float64),\n", " 'nn_weights_test2': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", @@ -621,9 +671,20 @@ " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]],\n", + " \n", + " [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", - " 'm_test2': Array([0.5], dtype=float64),\n", - " 'h_test2': Array([0.5], dtype=float64)},\n", + " 'm_test2': Array([0.5, 0.5], dtype=float64),\n", + " 'h_test2': Array([0.5, 0.5], dtype=float64)},\n", " {'gbar_test2': Array([123., 1.], dtype=float64),\n", " 'e_test2': Array([0., 0.], dtype=float64),\n", " 'nn_weights_test2': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", @@ -676,7 +737,7 @@ " 'h_test1': Array([0.5, 0.5], dtype=float64)})" ] }, - "execution_count": 10, + "execution_count": 85, "metadata": {}, "output_type": "execute_result" } From 00e96c0588c76f2305b4c9b1ccf3fca462eef655 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Mon, 26 May 2025 16:02:19 +0200 Subject: [PATCH 10/24] wip: save wip --- dev.ipynb | 535 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 462 insertions(+), 73 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index 0a59a2ba1..66ed077a6 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -26,21 +26,19 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from __future__ import annotations\n", "import jax\n", "import jax.numpy as jnp\n", - "import equinox as eqx\n", "import pandas as pd\n", "\n", "import networkx as nx\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from jax import vmap\n", - "# from graphjax.graph import MorphTree\n", "\n", "from typing import Optional, List, Dict, Any, Union, Set, Tuple\n", "from dataclasses import dataclass, field" @@ -48,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 140, "metadata": {}, "outputs": [], "source": [ @@ -56,10 +54,10 @@ " i_id_xyzr_p = np.loadtxt(fname)[:num_lines]\n", " \n", " node_attrs, edge_attrs = {}, {}\n", - " for i, id, x, y, z, r, j in i_id_xyzr_p:\n", - " node_attrs[int(i)] = {\"id\": int(id), \"x\": float(x), \"y\": float(y), \"z\": float(z), \"r\": float(r)}\n", - " if j != -1:\n", - " edge_attrs[int(j), int(i)] = {}\n", + " for i, id, x, y, z, r, p in i_id_xyzr_p.tolist(): # tolist: np.float64 -> float\n", + " node_attrs[int(i)] = {\"id\": int(id), \"x\": x, \"y\": y, \"z\": z, \"r\": r}\n", + " if p != -1:\n", + " edge_attrs[int(p), int(i)] = {}\n", " \n", " return MorphTree(node_attrs, edge_attrs)\n", "\n", @@ -99,26 +97,30 @@ " G = nx.DiGraph()\n", " G.add_nodes_from(self.node_attrs.items())\n", " G.add_edges_from((i, j, d) for (i, j), d in self.edge_attrs.items())\n", + " G.graph.update(self.global_attrs)\n", " return G\n", " \n", " @staticmethod\n", " def from_nx(G: nx.DiGraph) -> MorphTree:\n", " node_attrs = {n: G.nodes[n] for n in G.nodes}\n", " edge_attrs = {(i, j): G.edges[i, j] for i, j in G.edges}\n", - " return MorphTree(node_attrs, edge_attrs)\n", + " return MorphTree(node_attrs, edge_attrs, G.graph)\n", " \n", - " def to_pandas(self) -> Tuple[pd.DataFrame, pd.DataFrame]:\n", + " def to_pandas(self, return_global_attrs: bool = False) -> Tuple[pd.DataFrame, pd.DataFrame]:\n", " node_df = pd.DataFrame(self.node_attrs.values(), index=self.node_attrs.keys())\n", " edge_df = pd.DataFrame(self.edge_attrs.values(), index=self.edge_attrs.keys())\n", " edge_index = pd.MultiIndex.from_arrays(np.array(self.edges).T)\n", " edge_df = edge_df.set_index(edge_index)\n", + "\n", + " if return_global_attrs:\n", + " return node_df, edge_df, pd.Series(self.global_attrs)\n", " return node_df, edge_df\n", " \n", " @staticmethod\n", - " def from_pandas(node_df: pd.DataFrame, edge_df: pd.DataFrame) -> MorphTree:\n", + " def from_pandas(node_df: pd.DataFrame, edge_df: pd.DataFrame, global_attrs: pd.Series = pd.Series()) -> MorphTree:\n", " node_attrs = node_df.to_dict(orient=\"index\")\n", " edge_attrs = edge_df.to_dict(orient=\"index\")\n", - " return MorphTree(node_attrs, edge_attrs)\n", + " return MorphTree(node_attrs, edge_attrs, global_attrs.to_dict())\n", " \n", " def plot(self, **kwargs: Any) -> None:\n", " G = self.to_nx()\n", @@ -149,6 +151,11 @@ " print(i,j)\n", " self.edge_attrs[j, i] = self.edge_attrs.pop((i, j))\n", " return self\n", + " \n", + " def subgraph(self, nodes: List[int]) -> MorphTree:\n", + " node_attrs_subset = {i: self.node_attrs[i] for i in nodes}\n", + " edge_attrs_subset = {(i,j): attrs for (i,j), attrs in self.edge_attrs.items() if i in nodes and j in nodes}\n", + " return MorphTree(node_attrs_subset, edge_attrs_subset, self.global_attrs)\n", "\n", "def list_branches(tree: MorphTree, return_branchpoints: bool = False) -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", " G = tree.to_nx().to_undirected()\n", @@ -289,7 +296,6 @@ " comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", " comp_df = comp_df.set_index(\"idx\")\n", "\n", - " \n", " comp_attrs = comp_df.to_dict(orient=\"index\")\n", " comp_edges = sum(branch_edges, [])\n", " comp_edge_attrs = {(i,j): {\"comp_edge\": True, \"synapse\": False} for i,j in comp_edges}\n", @@ -298,6 +304,23 @@ " comp_tree = comp_tree.reindex_nodes(dict(zip(comp_df.index, range(len(comp_df)))))\n", " return comp_tree\n", "\n", + "def _add_meta_data(tree: MorphTree) -> MorphTree:\n", + " global_attrs = {\"channels\": {}, \"synapses\": {}, \"xyzr\": None} # TODO: add xyzr\n", + "\n", + " group_ids = {0: \"undefined\", 1: \"soma\", 2: \"axon\", 3: \"basal\", 4: \"apical\"}\n", + " fill_w = lambda x: np.full(len(tree.nodes), x)\n", + "\n", + " nodes_df, edge_df = tree.to_pandas()\n", + " nodes_df[\"cell\"] = fill_w(0)\n", + " nodes_df[\"comp\"] = np.arange(len(nodes_df))\n", + " nodes_df[\"id\"] = nodes_df[\"id\"].apply(lambda x: [group_ids[x]])\n", + " nodes_df = nodes_df.rename(columns={\"r\": \"radius\", \"l\": \"length\", \"id\": \"groups\"})\n", + " nodes_df[\"capacitance\"] = fill_w(1.0)\n", + " nodes_df[\"v\"] = fill_w(-70.0)\n", + " nodes_df[\"axial_resistivity\"] = fill_w(1000.0)\n", + "\n", + " return MorphTree.from_pandas(nodes_df, edge_df, pd.Series(global_attrs))\n", + "\n", "# def set_solve_order(tree: MorphTree, solve_order: List[int]) -> MorphTree:\n", "# # TODO: do we want to rm branchpoints and comp_edges?\n", "# return" @@ -305,7 +328,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 136, "metadata": {}, "outputs": [], "source": [ @@ -322,15 +345,34 @@ " tree.node_attrs[i].update(channel.params)\n", " tree.node_attrs[i].update(channel.states)\n", "\n", - "def tree_set(tree, inds, key, value):\n", - " if isinstance(inds[0], tuple):\n", - " for i, j in inds:\n", - " if key in tree.edge_attrs[(i,j)]:\n", - " tree.edge_attrs[(i,j)][key] = value\n", - " else:\n", - " for i in inds:\n", - " if key in tree.node_attrs[i]:\n", - " tree.node_attrs[i][key] = value\n", + "def tree_set(tree, key, value):\n", + " nodes_df, edge_df = tree.to_pandas()\n", + " # if ... if, since param could be in both nodes and edges\n", + " if key in nodes_df.columns:\n", + " not_na = ~nodes_df[key].isna()\n", + " nodes_df.loc[not_na, key] = value\n", + " if key in edge_df.columns:\n", + " not_na = ~edge_df[key].isna()\n", + " edge_df.loc[not_na, key] = value\n", + " return MorphTree.from_pandas(nodes_df, edge_df, pd.Series(tree.global_attrs))\n", + "\n", + " # not vectorized, but allows to modify in place\n", + " # if key in nodes_df.columns:\n", + " # for i in tree.node_attrs:\n", + " # if key in tree.node_attrs[i]:\n", + " # tree.node_attrs[i][key] = value\n", + " # if key in edge_df.columns:\n", + " # for i, j in tree.edges:\n", + " # if key in tree.edge_attrs[(i,j)]:\n", + " # tree.edge_attrs[(i,j)][key] = value\n", + "\n", + "\n", + "#TODO: split/merge similar to equinox\n", + "def split_tree(tree: MorphTree, nodes: List[int]) -> List[MorphTree]:\n", + " pass\n", + "\n", + "def merge_trees(trees: List[MorphTree]) -> MorphTree:\n", + " pass\n", "\n", "def tree_to_pytree(tree):\n", " nodes_df, edge_df = tree.to_pandas()\n", @@ -349,6 +391,9 @@ " jax_edges[key] = values\n", " return jax_nodes, jax_edges\n", "\n", + "def tree_view(tree: MorphTree, nodes: List[int]) -> MorphTree:\n", + " return tree.subgraph(nodes)\n", + "\n", "class DummySynapse:\n", " def __init__(self, name = None):\n", " self.name = self.__class__.__name__ if name is None else name\n", @@ -382,7 +427,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 137, "metadata": {}, "outputs": [], "source": [ @@ -409,9 +454,20 @@ }, { "cell_type": "code", - "execution_count": 103, + "execution_count": 138, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "MorphTree(nodes=2*['branch', 'branchpoint', 'id', 'l', 'x', 'y', 'z', 'r', 'gbar_test1', 'e_test1', 'nn_weights_test1', 'm_test1', 'h_test1', 'gbar_test2', 'e_test2', 'nn_weights_test2', 'm_test2', 'h_test2'], edges=1*['comp_edge', 'synapse'])" + ] + }, + "execution_count": 138, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "morph_comps.global_attrs[\"channels\"] = {}\n", "morph_comps.global_attrs[\"synapses\"] = {}\n", @@ -423,13 +479,17 @@ "tree_connect(morph_comps, [0, 1], [3, 2], DummySynapse(\"test1\"))\n", "tree_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test2\"))\n", "\n", - "tree_set(morph_comps, [0, 2], \"gbar_test1\", 123)\n", - "tree_set(morph_comps, [(0, 1)], \"gbar_test2\", 123)" + "tree_set(morph_comps, \"gbar_test1\", 123)\n", + "tree_set(morph_comps, \"gbar_test2\", 123)\n", + "\n", + "subtree = tree_view(morph_comps, np.arange(2,4))\n", + "\n", + "tree_set(subtree, \"l\", 99.99) # <-- setting on views works" ] }, { "cell_type": "code", - "execution_count": 104, + "execution_count": 139, "metadata": {}, "outputs": [ { @@ -478,13 +538,13 @@ " 0\n", " 0\n", " False\n", - " 1\n", - " 2.2\n", - " 2.1\n", - " 0.0\n", - " 0.0\n", + " 4\n", + " 244.227045\n", + " -38.814059\n", + " -467.221758\n", + " 61.146926\n", + " 0.24\n", " 1.0\n", - " 123.0\n", " 0.0\n", " [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", " 0.5\n", @@ -499,12 +559,54 @@ " 1\n", " 0\n", " True\n", + " 4\n", + " 0.000000\n", + " -35.240000\n", + " -400.770000\n", + " 11.680000\n", + " 0.40\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " \n", + " \n", + " 2\n", " 1\n", - " 0.0\n", + " False\n", + " 4\n", + " 4.273938\n", + " -34.766590\n", + " -399.802794\n", + " 12.197484\n", + " 0.40\n", " 1.0\n", " 0.0\n", - " 0.0\n", + " [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", + " 0.5\n", + " 0.5\n", " 1.0\n", + " 0.0\n", + " [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", + " 0.5\n", + " 0.5\n", + " \n", + " \n", + " 3\n", + " 1\n", + " True\n", + " 4\n", + " 0.000000\n", + " -33.900000\n", + " -397.850000\n", + " 12.150000\n", + " 0.40\n", " NaN\n", " NaN\n", " NaN\n", @@ -517,15 +619,292 @@ " NaN\n", " \n", " \n", - " 2\n", - " 1\n", + " 4\n", + " 2\n", + " False\n", + " 4\n", + " 240.982169\n", + " -46.285146\n", + " -486.534579\n", + " 27.280000\n", + " 0.24\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " \n", + " \n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " \n", + " \n", + " 228\n", + " 150\n", + " True\n", + " 4\n", + " 0.000000\n", + " -16.260000\n", + " -519.900000\n", + " 51.270000\n", + " 0.24\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " \n", + " \n", + " 229\n", + " 151\n", + " False\n", + " 4\n", + " 91.768980\n", + " -24.954915\n", + " -530.307179\n", + " 26.377928\n", + " 0.24\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " \n", + " \n", + " 230\n", + " 152\n", + " False\n", + " 4\n", + " 7.767618\n", + " -12.678710\n", + " -521.402776\n", + " 51.270000\n", + " 0.24\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " \n", + " \n", + " 231\n", + " 153\n", + " False\n", + " 4\n", + " 127.914756\n", + " 12.046325\n", + " -433.830644\n", + " 0.150000\n", + " 0.24\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " \n", + " \n", + " 232\n", + " 154\n", + " False\n", + " 4\n", + " 122.357698\n", + " -7.370122\n", + " -437.118248\n", + " 34.470000\n", + " 0.40\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " \n", + " \n", + "\n", + "

233 rows × 18 columns

\n", + "" + ], + "text/plain": [ + " branch branchpoint id l x y z \\\n", + "0 0 False 4 244.227045 -38.814059 -467.221758 61.146926 \n", + "1 0 True 4 0.000000 -35.240000 -400.770000 11.680000 \n", + "2 1 False 4 4.273938 -34.766590 -399.802794 12.197484 \n", + "3 1 True 4 0.000000 -33.900000 -397.850000 12.150000 \n", + "4 2 False 4 240.982169 -46.285146 -486.534579 27.280000 \n", + ".. ... ... .. ... ... ... ... \n", + "228 150 True 4 0.000000 -16.260000 -519.900000 51.270000 \n", + "229 151 False 4 91.768980 -24.954915 -530.307179 26.377928 \n", + "230 152 False 4 7.767618 -12.678710 -521.402776 51.270000 \n", + "231 153 False 4 127.914756 12.046325 -433.830644 0.150000 \n", + "232 154 False 4 122.357698 -7.370122 -437.118248 34.470000 \n", + "\n", + " r gbar_test1 e_test1 \\\n", + "0 0.24 1.0 0.0 \n", + "1 0.40 NaN NaN \n", + "2 0.40 1.0 0.0 \n", + "3 0.40 NaN NaN \n", + "4 0.24 NaN NaN \n", + ".. ... ... ... \n", + "228 0.24 NaN NaN \n", + "229 0.24 NaN NaN \n", + "230 0.24 NaN NaN \n", + "231 0.24 NaN NaN \n", + "232 0.40 NaN NaN \n", + "\n", + " nn_weights_test1 m_test1 h_test1 \\\n", + "0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", + "1 NaN NaN NaN \n", + "2 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", + "3 NaN NaN NaN \n", + "4 NaN NaN NaN \n", + ".. ... ... ... \n", + "228 NaN NaN NaN \n", + "229 NaN NaN NaN \n", + "230 NaN NaN NaN \n", + "231 NaN NaN NaN \n", + "232 NaN NaN NaN \n", + "\n", + " gbar_test2 e_test2 nn_weights_test2 \\\n", + "0 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", + "1 NaN NaN NaN \n", + "2 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", + "3 NaN NaN NaN \n", + "4 NaN NaN NaN \n", + ".. ... ... ... \n", + "228 NaN NaN NaN \n", + "229 NaN NaN NaN \n", + "230 NaN NaN NaN \n", + "231 NaN NaN NaN \n", + "232 NaN NaN NaN \n", + "\n", + " m_test2 h_test2 \n", + "0 0.5 0.5 \n", + "1 NaN NaN \n", + "2 0.5 0.5 \n", + "3 NaN NaN \n", + "4 NaN NaN \n", + ".. ... ... \n", + "228 NaN NaN \n", + "229 NaN NaN \n", + "230 NaN NaN \n", + "231 NaN NaN \n", + "232 NaN NaN \n", + "\n", + "[233 rows x 18 columns]" + ] + }, + "execution_count": 139, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "morph_comps.to_pandas()[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -538,15 +917,15 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", " \n", + " \n", " \n", " \n", " \n", @@ -559,15 +938,36 @@ " \n", " \n", " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -585,35 +985,31 @@ ], "text/plain": [ " branch branchpoint id l x y z r gbar_test1 e_test1 \\\n", - "0 0 False 1 2.2 2.1 0.0 0.0 1.0 123.0 0.0 \n", - "1 0 True 1 0.0 1.0 0.0 0.0 1.0 NaN NaN \n", - "2 1 False 1 1.0 0.5 0.0 0.0 1.0 123.0 0.0 \n", - "3 1 True 1 0.0 0.0 0.0 0.0 1.0 NaN NaN \n", - "4 2 False 3 2.6 0.0 1.3 0.0 1.0 NaN NaN \n", + "0 0 False 1 1.0 0.0 0.0 0.5 0.1 123.0 0.0 \n", + "1 0 True 1 0.0 0.0 0.0 1.0 0.1 NaN NaN \n", + "2 1 False 2 1.0 0.0 0.0 1.5 0.1 123.0 0.0 \n", + "3 2 False 3 2.0 0.0 0.0 2.0 0.1 NaN NaN \n", "\n", " nn_weights_test1 m_test1 h_test1 \\\n", "0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", "1 NaN NaN NaN \n", "2 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", "3 NaN NaN NaN \n", - "4 NaN NaN NaN \n", "\n", " gbar_test2 e_test2 nn_weights_test2 \\\n", "0 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", "1 NaN NaN NaN \n", "2 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", "3 NaN NaN NaN \n", - "4 NaN NaN NaN \n", "\n", " m_test2 h_test2 \n", "0 0.5 0.5 \n", "1 NaN NaN \n", "2 0.5 0.5 \n", - "3 NaN NaN \n", - "4 NaN NaN " + "3 NaN NaN " ] }, - "execution_count": 104, + "execution_count": 38, "metadata": {}, "output_type": "execute_result" } @@ -624,17 +1020,17 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "({'l': Array([2.2, 1. , 2.6], dtype=float64),\n", - " 'x': Array([2.1, 0.5, 0. ], dtype=float64),\n", - " 'y': Array([0. , 0. , 1.3], dtype=float64),\n", - " 'z': Array([0., 0., 0.], dtype=float64),\n", - " 'r': Array([1., 1., 1.], dtype=float64),\n", + "({'l': Array([1., 1., 2.], dtype=float64),\n", + " 'x': Array([0., 0., 0.], dtype=float64),\n", + " 'y': Array([0., 0., 0.], dtype=float64),\n", + " 'z': Array([0.5, 1.5, 2. ], dtype=float64),\n", + " 'r': Array([0.1, 0.1, 0.1], dtype=float64),\n", " 'gbar_test1': Array([123., 123.], dtype=float64),\n", " 'e_test1': Array([0., 0.], dtype=float64),\n", " 'nn_weights_test1': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", @@ -737,7 +1133,7 @@ " 'h_test1': Array([0.5, 0.5], dtype=float64)})" ] }, - "execution_count": 85, + "execution_count": 39, "metadata": {}, "output_type": "execute_result" } @@ -746,13 +1142,6 @@ "tree_to_pytree(morph_comps)" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": 1582, From 61780c4424e3c991670688124a6abd6c0f8404b5 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Mon, 26 May 2025 16:18:56 +0200 Subject: [PATCH 11/24] wip: save wip --- dev.ipynb | 705 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 440 insertions(+), 265 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index 66ed077a6..bf433eb71 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 140, + "execution_count": 204, "metadata": {}, "outputs": [], "source": [ @@ -328,7 +328,7 @@ }, { "cell_type": "code", - "execution_count": 136, + "execution_count": 218, "metadata": {}, "outputs": [], "source": [ @@ -349,37 +349,42 @@ " nodes_df, edge_df = tree.to_pandas()\n", " # if ... if, since param could be in both nodes and edges\n", " if key in nodes_df.columns:\n", - " not_na = ~nodes_df[key].isna()\n", - " nodes_df.loc[not_na, key] = value\n", + " valid = ~nodes_df[key].isna() & ~nodes_df.branchpoint\n", + " nodes_df.loc[valid, key] = value\n", " if key in edge_df.columns:\n", - " not_na = ~edge_df[key].isna()\n", - " edge_df.loc[not_na, key] = value\n", + " valid = ~edge_df[key].isna() & edge_df.synapse\n", + " edge_df.loc[valid, key] = value\n", " return MorphTree.from_pandas(nodes_df, edge_df, pd.Series(tree.global_attrs))\n", "\n", - " # not vectorized, but allows to modify in place\n", + " # # not vectorized, but allows to modify in place\n", + " # nodes_df, edge_df = tree.to_pandas()\n", " # if key in nodes_df.columns:\n", " # for i in tree.node_attrs:\n", " # if key in tree.node_attrs[i]:\n", " # tree.node_attrs[i][key] = value\n", " # if key in edge_df.columns:\n", - " # for i, j in tree.edges:\n", + " # for i, j in tree.edge_attrs:\n", " # if key in tree.edge_attrs[(i,j)]:\n", " # tree.edge_attrs[(i,j)][key] = value\n", "\n", "\n", "#TODO: split/merge similar to equinox\n", - "def split_tree(tree: MorphTree, nodes: List[int]) -> List[MorphTree]:\n", - " pass\n", - "\n", "def merge_trees(trees: List[MorphTree]) -> MorphTree:\n", - " pass\n", + " tree = trees[0]\n", + " for t in trees[1:]:\n", + " tree.node_attrs.update(t.node_attrs)\n", + " tree.edge_attrs.update(t.edge_attrs)\n", + " return tree\n", + "\n", + "# def split_tree(tree: MorphTree, nodes: List[int]) -> List[MorphTree]:\n", + "# pass\n", "\n", "def tree_to_pytree(tree):\n", " nodes_df, edge_df = tree.to_pandas()\n", " jax_nodes, jax_edges = {}, {}\n", " \n", " node_data = nodes_df.loc[~nodes_df.branchpoint]\n", - " node_data = node_data.drop(columns=[\"branch\", \"branchpoint\", \"id\"])\n", + " node_data = node_data.drop(columns=[\"branch\", \"branchpoint\", \"groups\"])\n", " for key in node_data.columns:\n", " values = jnp.array(node_data.loc[~node_data[key].isna(), key].to_list())\n", " jax_nodes[key] = values\n", @@ -427,7 +432,7 @@ }, { "cell_type": "code", - "execution_count": 137, + "execution_count": 219, "metadata": {}, "outputs": [], "source": [ @@ -449,47 +454,106 @@ "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[-3])\n", "\n", "morph_comps = compartmentalize(MorphTree.from_nx(jx_graph.copy()), num_comps=1)\n", + "morph_comps = _add_meta_data(morph_comps)\n", "# jx_comps = build_compartment_graph(jx_graph, ncomp=1)" ] }, { "cell_type": "code", - "execution_count": 138, + "execution_count": 220, + "metadata": {}, + "outputs": [], + "source": [ + "tree_insert(morph_comps, [0, 2], DummyChannel(\"test1\"))\n", + "tree_insert(morph_comps, [0, 2], DummyChannel(\"test2\"))\n", + "\n", + "tree_connect(morph_comps, [0, 1], [3, 2], DummySynapse(\"test1\"))\n", + "tree_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test2\"))\n", + "\n", + "tree_set(morph_comps, \"gbar_test1\", 123)\n", + "tree_set(morph_comps, \"gbar_test2\", 123)\n", + "\n", + "subtree = tree_view(morph_comps, list(range(0,2)))\n", + "subtree = tree_set(subtree, \"length\", 99.99) # <-- setting on views works\n", + "# morph_comps = merge_trees([morph_comps, subtree])" + ] + }, + { + "cell_type": "code", + "execution_count": 217, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "MorphTree(nodes=2*['branch', 'branchpoint', 'id', 'l', 'x', 'y', 'z', 'r', 'gbar_test1', 'e_test1', 'nn_weights_test1', 'm_test1', 'h_test1', 'gbar_test2', 'e_test2', 'nn_weights_test2', 'm_test2', 'h_test2'], edges=1*['comp_edge', 'synapse'])" + "{0: {'branch': 0,\n", + " 'branchpoint': False,\n", + " 'groups': ['apical'],\n", + " 'length': 244.22704536220328,\n", + " 'x': -38.814059082992166,\n", + " 'y': -467.2217575574461,\n", + " 'z': 61.146926321832275,\n", + " 'radius': 0.24,\n", + " 'cell': 0,\n", + " 'comp': 0,\n", + " 'capacitance': 1.0,\n", + " 'v': -70.0,\n", + " 'axial_resistivity': 1000.0,\n", + " 'gbar_test1': 1.0,\n", + " 'e_test1': 0.0,\n", + " 'nn_weights_test1': Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", + " 'm_test1': 0.5,\n", + " 'h_test1': 0.5,\n", + " 'gbar_test2': 1.0,\n", + " 'e_test2': 0.0,\n", + " 'nn_weights_test2': Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", + " 'm_test2': 0.5,\n", + " 'h_test2': 0.5},\n", + " 1: {'branch': 0,\n", + " 'branchpoint': True,\n", + " 'groups': ['apical'],\n", + " 'length': 0.0,\n", + " 'x': -35.24,\n", + " 'y': -400.77,\n", + " 'z': 11.68,\n", + " 'radius': 0.4,\n", + " 'cell': 0,\n", + " 'comp': 1,\n", + " 'capacitance': 1.0,\n", + " 'v': -70.0,\n", + " 'axial_resistivity': 1000.0}}" ] }, - "execution_count": 138, + "execution_count": 217, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "morph_comps.global_attrs[\"channels\"] = {}\n", - "morph_comps.global_attrs[\"synapses\"] = {}\n", - "\n", - "\n", - "tree_insert(morph_comps, [0, 2], DummyChannel(\"test1\"))\n", - "tree_insert(morph_comps, [0, 2], DummyChannel(\"test2\"))\n", - "\n", - "tree_connect(morph_comps, [0, 1], [3, 2], DummySynapse(\"test1\"))\n", - "tree_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test2\"))\n", - "\n", - "tree_set(morph_comps, \"gbar_test1\", 123)\n", - "tree_set(morph_comps, \"gbar_test2\", 123)\n", - "\n", - "subtree = tree_view(morph_comps, np.arange(2,4))\n", - "\n", - "tree_set(subtree, \"l\", 99.99) # <-- setting on views works" + "subtree.node_attrs" ] }, { "cell_type": "code", - "execution_count": 139, + "execution_count": 201, "metadata": {}, "outputs": [ { @@ -515,12 +579,15 @@ " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -538,12 +605,15 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -559,12 +629,15 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -580,12 +653,15 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -601,12 +677,15 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -622,12 +701,15 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -659,17 +741,23 @@ " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -685,12 +773,15 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -706,12 +797,15 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -727,12 +821,15 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -748,12 +845,15 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -767,35 +867,35 @@ " \n", " \n", "
branchbranchpointidlxyzrgbar_test1e_test1nn_weights_test1m_test1h_test1gbar_test2e_test2nn_weights_test2m_test2h_test2
00False11.00.50.00.01.00.50.1123.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.5
3110True10.00.00.00.01.00.1NaNNaNNaNNaN
421False21.00.00.01.50.1123.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.51.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.5
32False32.62.00.01.30.01.02.00.1NaNNaNNaNbranchbranchpointidlgroupslengthxyzrradiuscellcomp...gbar_test1e_test1nn_weights_test100False4[apical]244.227045-38.814059-467.22175861.1469260.2400...1.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...10True4[apical]0.000000-35.240000-400.77000011.6800000.4001...NaNNaNNaN21False4[apical]4.273938-34.766590-399.80279412.1974840.4002...1.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...31True4[apical]0.000000-33.900000-397.85000012.1500000.4003...NaNNaNNaN42False4[apical]240.982169-46.285146-486.53457927.2800000.2404...NaNNaNNaN..................
228150True4[apical]0.000000-16.260000-519.90000051.2700000.240228...NaNNaNNaN229151False4[apical]91.768980-24.954915-530.30717926.3779280.240229...NaNNaNNaN230152False4[apical]7.767618-12.678710-521.40277651.2700000.240230...NaNNaNNaN231153False4[apical]127.91475612.046325-433.8306440.1500000.240231...NaNNaNNaN232154False4[apical]122.357698-7.370122-437.11824834.4700000.400232...NaNNaNNaN
\n", - "

233 rows × 18 columns

\n", + "

233 rows × 23 columns

\n", "
" ], "text/plain": [ - " branch branchpoint id l x y z \\\n", - "0 0 False 4 244.227045 -38.814059 -467.221758 61.146926 \n", - "1 0 True 4 0.000000 -35.240000 -400.770000 11.680000 \n", - "2 1 False 4 4.273938 -34.766590 -399.802794 12.197484 \n", - "3 1 True 4 0.000000 -33.900000 -397.850000 12.150000 \n", - "4 2 False 4 240.982169 -46.285146 -486.534579 27.280000 \n", - ".. ... ... .. ... ... ... ... \n", - "228 150 True 4 0.000000 -16.260000 -519.900000 51.270000 \n", - "229 151 False 4 91.768980 -24.954915 -530.307179 26.377928 \n", - "230 152 False 4 7.767618 -12.678710 -521.402776 51.270000 \n", - "231 153 False 4 127.914756 12.046325 -433.830644 0.150000 \n", - "232 154 False 4 122.357698 -7.370122 -437.118248 34.470000 \n", + " branch branchpoint groups length x y \\\n", + "0 0 False [apical] 244.227045 -38.814059 -467.221758 \n", + "1 0 True [apical] 0.000000 -35.240000 -400.770000 \n", + "2 1 False [apical] 4.273938 -34.766590 -399.802794 \n", + "3 1 True [apical] 0.000000 -33.900000 -397.850000 \n", + "4 2 False [apical] 240.982169 -46.285146 -486.534579 \n", + ".. ... ... ... ... ... ... \n", + "228 150 True [apical] 0.000000 -16.260000 -519.900000 \n", + "229 151 False [apical] 91.768980 -24.954915 -530.307179 \n", + "230 152 False [apical] 7.767618 -12.678710 -521.402776 \n", + "231 153 False [apical] 127.914756 12.046325 -433.830644 \n", + "232 154 False [apical] 122.357698 -7.370122 -437.118248 \n", "\n", - " r gbar_test1 e_test1 \\\n", - "0 0.24 1.0 0.0 \n", - "1 0.40 NaN NaN \n", - "2 0.40 1.0 0.0 \n", - "3 0.40 NaN NaN \n", - "4 0.24 NaN NaN \n", - ".. ... ... ... \n", - "228 0.24 NaN NaN \n", - "229 0.24 NaN NaN \n", - "230 0.24 NaN NaN \n", - "231 0.24 NaN NaN \n", - "232 0.40 NaN NaN \n", + " z radius cell comp ... gbar_test1 e_test1 \\\n", + "0 61.146926 0.24 0 0 ... 1.0 0.0 \n", + "1 11.680000 0.40 0 1 ... NaN NaN \n", + "2 12.197484 0.40 0 2 ... 1.0 0.0 \n", + "3 12.150000 0.40 0 3 ... NaN NaN \n", + "4 27.280000 0.24 0 4 ... NaN NaN \n", + ".. ... ... ... ... ... ... ... \n", + "228 51.270000 0.24 0 228 ... NaN NaN \n", + "229 26.377928 0.24 0 229 ... NaN NaN \n", + "230 51.270000 0.24 0 230 ... NaN NaN \n", + "231 0.150000 0.24 0 231 ... NaN NaN \n", + "232 34.470000 0.40 0 232 ... NaN NaN \n", "\n", " nn_weights_test1 m_test1 h_test1 \\\n", "0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", @@ -810,18 +910,18 @@ "231 NaN NaN NaN \n", "232 NaN NaN NaN \n", "\n", - " gbar_test2 e_test2 nn_weights_test2 \\\n", - "0 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", - "1 NaN NaN NaN \n", - "2 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", - "3 NaN NaN NaN \n", - "4 NaN NaN NaN \n", - ".. ... ... ... \n", - "228 NaN NaN NaN \n", - "229 NaN NaN NaN \n", - "230 NaN NaN NaN \n", - "231 NaN NaN NaN \n", - "232 NaN NaN NaN \n", + " gbar_test2 e_test2 nn_weights_test2 \\\n", + "0 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", + "1 NaN NaN NaN \n", + "2 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", + "3 NaN NaN NaN \n", + "4 NaN NaN NaN \n", + ".. ... ... ... \n", + "228 NaN NaN NaN \n", + "229 NaN NaN NaN \n", + "230 NaN NaN NaN \n", + "231 NaN NaN NaN \n", + "232 NaN NaN NaN \n", "\n", " m_test2 h_test2 \n", "0 0.5 0.5 \n", @@ -836,180 +936,10 @@ "231 NaN NaN \n", "232 NaN NaN \n", "\n", - "[233 rows x 18 columns]" - ] - }, - "execution_count": 139, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "morph_comps.to_pandas()[0]" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
branchbranchpointidlxyzrgbar_test1e_test1nn_weights_test1m_test1h_test1gbar_test2e_test2nn_weights_test2m_test2h_test2
00False11.00.00.00.50.1123.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.51.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.5
10True10.00.00.01.00.1NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
21False21.00.00.01.50.1123.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.51.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.5
32False32.00.00.02.00.1NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
\n", - "
" - ], - "text/plain": [ - " branch branchpoint id l x y z r gbar_test1 e_test1 \\\n", - "0 0 False 1 1.0 0.0 0.0 0.5 0.1 123.0 0.0 \n", - "1 0 True 1 0.0 0.0 0.0 1.0 0.1 NaN NaN \n", - "2 1 False 2 1.0 0.0 0.0 1.5 0.1 123.0 0.0 \n", - "3 2 False 3 2.0 0.0 0.0 2.0 0.1 NaN NaN \n", - "\n", - " nn_weights_test1 m_test1 h_test1 \\\n", - "0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", - "1 NaN NaN NaN \n", - "2 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", - "3 NaN NaN NaN \n", - "\n", - " gbar_test2 e_test2 nn_weights_test2 \\\n", - "0 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", - "1 NaN NaN NaN \n", - "2 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", - "3 NaN NaN NaN \n", - "\n", - " m_test2 h_test2 \n", - "0 0.5 0.5 \n", - "1 NaN NaN \n", - "2 0.5 0.5 \n", - "3 NaN NaN " + "[233 rows x 23 columns]" ] }, - "execution_count": 38, + "execution_count": 201, "metadata": {}, "output_type": "execute_result" } @@ -1020,18 +950,263 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 150, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "({'l': Array([1., 1., 2.], dtype=float64),\n", - " 'x': Array([0., 0., 0.], dtype=float64),\n", - " 'y': Array([0., 0., 0.], dtype=float64),\n", - " 'z': Array([0.5, 1.5, 2. ], dtype=float64),\n", - " 'r': Array([0.1, 0.1, 0.1], dtype=float64),\n", - " 'gbar_test1': Array([123., 123.], dtype=float64),\n", + "({'length': Array([2.44227045e+02, 4.27393845e+00, 2.40982169e+02, 4.67513057e+01,\n", + " 8.65335301e+01, 1.71028475e+01, 2.46046913e+01, 5.00520562e+01,\n", + " 5.37613212e+01, 1.59714426e+02, 7.48997041e+01, 1.86023601e+01,\n", + " 1.17733295e+02, 3.48567067e+00, 6.99059144e+01, 4.18909298e+00,\n", + " 1.13682833e+02, 1.63440324e+01, 8.36221267e+01, 7.14833481e+01,\n", + " 5.60078230e+01, 8.65139844e+00, 1.19434577e+01, 1.18341624e+01,\n", + " 6.04821169e+01, 2.22652195e+00, 8.64983664e+01, 1.01865650e+02,\n", + " 1.04995175e+02, 1.81920197e+02, 1.14303517e+02, 1.24831143e+01,\n", + " 8.32100003e+00, 5.84467372e+01, 6.03573930e+01, 7.07951637e+00,\n", + " 7.97070260e+00, 6.54202812e+01, 3.98980463e+01, 4.73884329e+01,\n", + " 1.11205690e+01, 1.58199233e+01, 1.06745317e+01, 1.93803826e+02,\n", + " 4.68279814e+01, 1.16410913e+02, 2.18482129e+01, 3.98674512e+01,\n", + " 1.31019920e+01, 1.14727338e+02, 2.62038740e+01, 2.36348559e+01,\n", + " 1.46372243e+02, 1.77078541e+02, 1.51908215e+02, 1.88632174e+01,\n", + " 1.99484663e+01, 2.01271439e+02, 9.98779052e+01, 7.20884214e+01,\n", + " 1.03907121e+02, 3.36359252e+01, 5.89085479e+01, 1.07287479e+02,\n", + " 7.34204122e+01, 2.08664292e+01, 6.14484518e+01, 7.76717167e+00,\n", + " 3.75958736e+01, 5.98194156e+00, 8.28050749e+01, 5.15007803e+01,\n", + " 7.69670339e+01, 1.38513551e+02, 5.89333860e-01, 7.13845088e+01,\n", + " 2.47290064e+02, 1.03945877e+01, 1.37263347e+02, 2.07062881e+02,\n", + " 8.30791299e+01, 1.37880444e+01, 2.48048336e+01, 2.33607253e+01,\n", + " 1.74379156e+01, 5.70210922e+01, 5.34781853e+01, 7.01609823e+01,\n", + " 1.41706274e+02, 1.99370310e+02, 2.27512040e+02, 1.94238703e+02,\n", + " 5.71602082e+01, 2.87768195e+01, 9.24722613e+01, 2.51768663e+00,\n", + " 8.65304227e+01, 1.82482876e-01, 3.18533866e+01, 6.42759470e+01,\n", + " 1.39461130e+01, 4.02934985e+01, 7.98859607e+01, 1.59913083e+02,\n", + " 2.82131445e+01, 1.00706363e+02, 4.29941742e+01, 2.31970368e+02,\n", + " 5.13527546e+01, 1.50636642e+01, 6.75241154e+01, 6.61563113e+01,\n", + " 1.26906107e+01, 1.76133011e+02, 4.50523713e+01, 2.06259293e+02,\n", + " 1.87169885e+01, 1.47306550e+01, 3.54588338e+01, 1.75242344e+02,\n", + " 1.32771667e+00, 1.29183383e+02, 5.74656307e-01, 1.40209297e+02,\n", + " 1.78636825e+01, 7.75760254e+01, 5.89367355e+01, 1.18174494e+02,\n", + " 7.61007831e+01, 6.06704256e+01, 9.94571441e+01, 9.31158162e+01,\n", + " 1.92990563e+02, 8.83708697e+01, 1.56182708e+02, 2.01756276e+01,\n", + " 4.55395873e+01, 3.14180157e+02, 4.96918789e+01, 1.46905134e+02,\n", + " 1.03873063e+02, 1.42322205e+02, 3.09882545e+01, 3.72726316e+01,\n", + " 6.08114959e+01, 2.70516732e+01, 6.01662185e+01, 8.38092975e+01,\n", + " 4.53456511e+01, 2.19301346e+02, 2.05210304e+02, 9.17689802e+01,\n", + " 7.76761757e+00, 1.27914756e+02, 1.22357698e+02], dtype=float64),\n", + " 'x': Array([-3.88140591e+01, -3.47665895e+01, -4.62851460e+01, -2.86055828e+01,\n", + " -6.04664941e+01, -2.22141373e+01, -2.17649065e+01, -1.46674384e+01,\n", + " -2.65934838e+01, -7.64561829e+00, -5.55926798e+00, -2.19500000e+00,\n", + " -1.62525338e+01, -4.50000000e-02, -8.90751403e+00, 4.35000000e-01,\n", + " 7.77627645e+00, -7.36059522e-01, -1.65841611e+01, 8.14565057e-01,\n", + " 2.13285961e+01, 6.89445123e+00, 4.05295155e+00, 7.38500000e+00,\n", + " 1.67828190e+01, 7.71000000e+00, 2.01344625e+00, 1.08146263e+01,\n", + " 2.52294648e+00, 1.77869711e+01, 2.53586342e+01, 1.96899895e+00,\n", + " -1.43191395e+00, 1.07794505e+01, -3.38124350e+00, -1.10783510e+01,\n", + " -1.35700000e+01, -2.17445329e+01, -2.04646257e+01, -2.40601176e+01,\n", + " -2.73733044e+01, -3.17616719e+01, -3.12286604e+01, -3.46899208e+01,\n", + " -4.09685246e+01, -4.65120057e+01, -3.84031315e+01, -1.34834327e+01,\n", + " -1.73996943e+01, -2.91027177e+01, -1.28358122e+01, -1.45804066e+01,\n", + " -1.11253485e+01, -8.15036285e+00, -2.21252519e+01, -2.70002952e+01,\n", + " -2.46579547e+01, -6.35780453e+01, -4.48365602e+01, -3.92184464e+01,\n", + " -7.13437925e+01, -5.51445682e+01, -6.44816671e+01, -9.35387104e+01,\n", + " -6.91735810e+01, 1.03711686e+01, 1.74618476e+01, 5.43191123e+00,\n", + " 1.19414126e+01, 2.84773808e+00, 1.93901408e+00, 1.93595787e-01,\n", + " 1.29500000e+00, -2.72412240e+01, -5.80263563e+00, 1.46500000e+00,\n", + " 2.22187553e+01, 2.53570369e+00, -1.84266862e+00, 1.51830631e+01,\n", + " 2.20613544e+01, -3.84324259e+00, 1.71926423e+00, -5.57872256e-01,\n", + " -7.05500000e+00, -1.55119060e+01, -4.13728233e+00, -3.67836032e+01,\n", + " -6.20384343e+01, 1.05045409e+01, -2.26490914e+01, 1.32178956e+01,\n", + " 7.66484909e+00, 2.31079088e+01, 1.61021887e+01, 1.46392832e+01,\n", + " 1.10439022e+01, 1.58050000e+01, 1.78764087e+01, 2.12141509e+01,\n", + " 1.89122741e+01, 2.25274810e+01, 3.25100849e+01, 2.20398342e+01,\n", + " 1.89171231e+01, 5.45815165e+01, 5.40631551e+01, 8.34180477e+01,\n", + " 2.02817763e+01, 1.98801349e+01, 1.25974545e+01, 2.77192419e+01,\n", + " 2.20200000e+01, 2.96250976e+01, 3.23790033e+01, 5.64145841e+01,\n", + " 2.72277182e+01, 2.94151398e+01, 2.78960365e+01, 6.50720438e+01,\n", + " 3.15165333e+01, 5.63451453e+01, 3.10089173e+01, 1.77797413e+01,\n", + " 1.11620758e+01, 9.16106710e+00, 9.64909680e+00, 1.29319048e+01,\n", + " -5.55020829e+00, 2.96935061e+01, 2.25534511e+01, 5.56528605e+01,\n", + " 9.99225200e+01, 6.09454728e+01, 2.10102712e+01, 2.17317292e+01,\n", + " 2.82162141e+01, 7.31353939e+01, 4.62060688e+01, 9.44369001e+01,\n", + " 9.65242301e+01, -1.17380615e+01, -9.09180601e+00, -4.08751305e+00,\n", + " -1.72995328e+01, -3.10644853e+01, -4.28129473e+01, 6.47747363e+01,\n", + " 4.36760765e+01, 4.51429852e+01, 2.91750433e+01, -2.49549155e+01,\n", + " -1.26787102e+01, 1.20463251e+01, -7.37012198e+00], dtype=float64),\n", + " 'y': Array([-467.22175756, -399.80279422, -486.5345792 , -387.37532949,\n", + " -414.1453725 , -372.96551637, -377.3156131 , -353.98109982,\n", + " -376.98191136, -303.34552605, -358.39305046, -261.665 ,\n", + " -285.39362573, -254.215 , -266.40405108, -252.16 ,\n", + " -281.71696586, -244.85748401, -260.2859902 , -214.87275928,\n", + " -232.50102171, -183.59455434, -184.05942731, -181.41 ,\n", + " -194.19403766, -179.465 , -192.55559887, -152.12482716,\n", + " -159.71766977, -77.08047503, -135.40164775, -5.83329182,\n", + " 3.88615594, 7.08749238, 8.8679957 , 12.04773412,\n", + " 13.225 , 12.61433384, 25.35064568, 58.31648265,\n", + " 45.93333923, 51.6311146 , 53.87829662, 72.59061764,\n", + " 67.5258203 , 90.24287678, 62.48958086, 17.41335817,\n", + " 16.59322005, 30.47593334, 18.89287553, 25.87304953,\n", + " 34.73637081, 46.83288325, 71.8043282 , 27.79545894,\n", + " 19.7320453 , 106.42462676, 63.67345983, 28.461845 ,\n", + " 13.60008591, 60.41825342, 51.51458261, 103.55194279,\n", + " 97.88617877, 11.693338 , 5.92279773, 11.2442272 ,\n", + " 13.02718082, 13.8047606 , 36.66509591, 21.27139234,\n", + " 13.865 , 82.42212564, 37.49542511, 13.58 ,\n", + " 16.19182246, 13.55030688, 14.24151464, 65.01517003,\n", + " 28.39995684, 24.25018969, 30.79639145, 14.44969604,\n", + " 21.1 , 25.70793736, 38.95245081, 43.61421049,\n", + " 56.63902138, 104.13980011, 128.72752265, 61.24197344,\n", + " 56.74388898, 80.96430726, 100.16385372, 17.57025633,\n", + " 37.5829197 , 17.47 , 19.03547843, 22.4971067 ,\n", + " 17.6838308 , 38.1357177 , 43.22117954, 65.74640932,\n", + " 47.65934149, 71.65161919, 50.48598164, 56.32578249,\n", + " 34.38530483, 54.39253945, 76.57172314, 68.73963285,\n", + " 61.15 , 129.01740518, 80.26277401, 76.98769888,\n", + " 31.4711477 , 44.24275793, 51.97663607, 114.39658219,\n", + " 51.13726417, 121.04355091, 66.35524526, 114.98295441,\n", + " 80.27069362, 108.96831315, 96.68302983, 151.95575124,\n", + " 127.09725403, -2.67126416, 9.57396065, 1.81999783,\n", + " 41.86340217, -208.54174156, -130.79601473, -223.35724107,\n", + " -219.61857652, -327.27298222, -235.51987584, -285.77979536,\n", + " -265.36770569, -209.22123097, -188.67837147, -186.40151314,\n", + " -208.19400105, -238.99450251, -223.94711117, -218.78824582,\n", + " -216.75015638, -461.63075952, -467.24896436, -530.30717898,\n", + " -521.40277554, -433.83064446, -437.11824757], dtype=float64),\n", + " 'z': Array([ 61.14692632, 12.19748436, 27.28 , 25.76 ,\n", + " 11.51407401, 17.97892053, 13.97488458, 9.6433186 ,\n", + " -4.4 , 5.27622108, -4.67527252, 0.76 ,\n", + " 28.87 , 8.565 , -11.25195396, 11.77 ,\n", + " 34.33086009, 8.37256587, 43.27 , -2.23751834,\n", + " 15.07087261, 4.44270864, 6.41105726, 14.395 ,\n", + " 29.76343097, 19.835 , 30.60567925, 5.06034567,\n", + " 35.99978727, 1.84 , 44.08334803, 0. ,\n", + " 0. , 17.28816403, 30.10524862, 58.25343038,\n", + " 51.36 , 48.43476897, 56.67776162, 62.79 ,\n", + " 53.24066087, 60.93608537, 55.97186959, 35.18036425,\n", + " 58.73176729, 53.04 , 57.68 , 41.53315306,\n", + " 53.36 , 26.39211569, 34.5980048 , 31.59748853,\n", + " 25.0789444 , -32.10959913, 17.94486003, 53.10575416,\n", + " 49.45136379, 50.12462076, 31.64510844, 39.82193807,\n", + " 41.37762411, 47.0270826 , 61.04 , 38.71177192,\n", + " 43.42675924, 46.82048985, 37.3824518 , 37.78761858,\n", + " 20.64790945, 42.47678577, 31.10010505, 24.42659665,\n", + " 6.635 , 38.91897803, 12.56 , 3.84 ,\n", + " 19.38012979, 44.71551285, -28.97702095, 53.88555438,\n", + " 46.94412938, 30.79487086, 17.68 , 21.03781985,\n", + " 33.54 , 23.16780124, 23.12 , 14.8 ,\n", + " 22.79895063, 17.89706698, 54.31 , -22.33046626,\n", + " 24.56167616, 8.23 , 5.59 , 26.23 ,\n", + " 30.63 , 26.23 , 41.29887915, 17.00837525,\n", + " 31.40269374, 13.69093954, 29.31746084, 19.04132129,\n", + " 24.5473551 , 25.04 , 15.84 , 10.179687 ,\n", + " 21.76 , 15.44924698, 10.58139591, 18.15 ,\n", + " 15.68 , 5.72997792, 0.91787377, 53.70443838,\n", + " 50.42479344, 54.85576002, 49.55335055, 59.06966685,\n", + " 56.33915476, 58.88 , 56.56 , 34.01003695,\n", + " 30.71 , 58.7655592 , 20.02441116, 15.76 ,\n", + " 16.30609289, 15.59233597, 40.87062569, 39.75 ,\n", + " 33.77031441, 38.62313788, 4.15 , 45.45387938,\n", + " 48.05727869, 39.06053515, 34.91626415, 22.92708681,\n", + " 40.99827221, 36.08 , 20.57528003, 40.79519918,\n", + " 45.52 , 42.24970713, 29.64160623, 36.28412232,\n", + " 37.63106542, 1.95884902, -2.28342966, 26.3779279 ,\n", + " 51.27 , 0.15 , 34.47 ], dtype=float64),\n", + " 'radius': Array([0.24 , 0.4 , 0.24 , 0.4 , 0.24 ,\n", + " 0.4 , 0.24 , 0.4 , 0.24 , 0.57828469,\n", + " 0.24 , 0.79 , 0.4 , 0.87 , 0.24 ,\n", + " 0.87 , 0.24 , 0.87 , 0.24 , 0.87 ,\n", + " 0.4 , 1.10211933, 0.72973568, 1.18 , 0.4 ,\n", + " 1.18 , 0.4 , 1.03 , 0.4 , 1.5 ,\n", + " 0.46888305, 6.36039227, 7.96 , 0.71 , 1.10336459,\n", + " 1.18544992, 0.79 , 0.55 , 0.55 , 0.55 ,\n", + " 0.55 , 0.55 , 0.55 , 0.24 , 0.55 ,\n", + " 0.24 , 0.55 , 0.87 , 0.55 , 0.4 ,\n", + " 0.67599993, 0.55 , 0.55 , 0.4 , 0.24 ,\n", + " 0.55 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", + " 0.4 , 0.4 , 0.4 , 0.4 , 0.24 ,\n", + " 0.55 , 0.4 , 0.55 , 0.55 , 0.55 ,\n", + " 0.55 , 0.55 , 0.475 , 0.4 , 0.55 ,\n", + " 0.87 , 0.4 , 1.34 , 0.43771301, 0.4 ,\n", + " 0.4 , 0.4 , 0.4 , 1.03 , 0.475 ,\n", + " 0.55 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", + " 0.4 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", + " 0.87 , 0.4 , 0.87 , 0.4 , 0.24 ,\n", + " 0.55 , 0.24 , 0.24 , 0.24 , 0.24 ,\n", + " 0.24 , 0.24 , 0.4 , 0.4 , 0.31876093,\n", + " 0.4 , 0.24 , 0.24 , 0.4 , 0.24 ,\n", + " 0.4 , 0.41539049, 0.42840312, 0.4 , 0.4 ,\n", + " 0.4 , 0.4 , 0.4 , 0.24 , 0.24 ,\n", + " 0.24 , 0.24 , 0.24 , 0.24 , 0.4 ,\n", + " 0.4 , 1.18 , 0.55 , 0.55 , 0.4 ,\n", + " 0.4 , 0.4 , 0.24 , 0.4 , 0.4 ,\n", + " 0.24 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", + " 0.4 , 0.24 , 0.24 , 0.24 , 0.24 ,\n", + " 0.24 , 0.24 , 0.24 , 0.24 , 0.4 ], dtype=float64),\n", + " 'cell': Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0], dtype=int64),\n", + " 'comp': Array([ 0, 2, 4, 5, 7, 8, 10, 12, 14, 15, 17, 19, 21,\n", + " 22, 24, 25, 27, 28, 30, 31, 33, 35, 37, 39, 41, 43,\n", + " 45, 46, 48, 49, 51, 53, 55, 57, 59, 61, 63, 65, 66,\n", + " 68, 69, 71, 73, 75, 76, 77, 78, 79, 81, 83, 84, 86,\n", + " 88, 89, 90, 91, 93, 95, 96, 97, 99, 100, 102, 103, 104,\n", + " 105, 107, 109, 111, 112, 114, 115, 117, 119, 120, 121, 123, 125,\n", + " 127, 129, 130, 131, 133, 135, 136, 138, 140, 142, 143, 144, 145,\n", + " 146, 147, 149, 150, 151, 153, 155, 157, 159, 161, 163, 165, 167,\n", + " 168, 169, 170, 171, 172, 174, 176, 177, 178, 180, 181, 182, 183,\n", + " 185, 187, 189, 190, 191, 192, 193, 194, 196, 197, 199, 200, 201,\n", + " 202, 204, 205, 206, 207, 208, 209, 211, 212, 214, 215, 216, 217,\n", + " 219, 220, 222, 223, 224, 225, 226, 227, 229, 230, 231, 232], dtype=int64),\n", + " 'capacitance': Array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1.], dtype=float64),\n", + " 'v': Array([-70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70.], dtype=float64),\n", + " 'axial_resistivity': Array([1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000.], dtype=float64),\n", + " 'gbar_test1': Array([1., 1.], dtype=float64),\n", " 'e_test1': Array([0., 0.], dtype=float64),\n", " 'nn_weights_test1': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", @@ -1081,7 +1256,7 @@ " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", " 'm_test2': Array([0.5, 0.5], dtype=float64),\n", " 'h_test2': Array([0.5, 0.5], dtype=float64)},\n", - " {'gbar_test2': Array([123., 1.], dtype=float64),\n", + " {'gbar_test2': Array([1., 1.], dtype=float64),\n", " 'e_test2': Array([0., 0.], dtype=float64),\n", " 'nn_weights_test2': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", @@ -1133,7 +1308,7 @@ " 'h_test1': Array([0.5, 0.5], dtype=float64)})" ] }, - "execution_count": 39, + "execution_count": 150, "metadata": {}, "output_type": "execute_result" } From c86d0fee953d4be77c3ae0947dc8fb31c94bd05b Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Tue, 27 May 2025 20:25:49 +0200 Subject: [PATCH 12/24] wip: build xyzr default --- dev.ipynb | 2459 +++++++++++++++++++++++++++-------------------------- 1 file changed, 1236 insertions(+), 1223 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index bf433eb71..b3feac06b 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 204, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -122,12 +122,13 @@ " edge_attrs = edge_df.to_dict(orient=\"index\")\n", " return MorphTree(node_attrs, edge_attrs, global_attrs.to_dict())\n", " \n", - " def plot(self, **kwargs: Any) -> None:\n", + " def plot(self, dims=(0,1),**kwargs: Any) -> None:\n", " G = self.to_nx()\n", " pos = {}\n", + " dims2axes = {0: \"x\", 1: \"y\", 2: \"z\"}\n", " for n, attr in G.nodes(data=True):\n", " if \"x\" in attr: # assume y is also present\n", - " pos[n] = (attr[\"x\"], attr[\"y\"])\n", + " pos[n] = (attr[dims2axes[dims[0]]], attr[dims2axes[dims[1]]])\n", " nx.draw(G, pos, with_labels=True, **kwargs)\n", " plt.show()\n", "\n", @@ -220,6 +221,27 @@ " return branches, branchpoints, branchpoint_edges\n", " return branches\n", "\n", + "def _find_swc_tracing_interruptions(tree: MorphTree) -> np.ndarray:\n", + " G = tree.to_nx()\n", + " degree_is_2 = lambda n: G.out_degree(n) + G.in_degree(n) == 2\n", + "\n", + " interrupt_edges = []\n", + " for n in G.nodes:\n", + " if len(parents := list(G.predecessors(n))) > 0:\n", + " p = parents[0] \n", + " if p != n-1 and degree_is_2(n) and degree_is_2(p):\n", + " interrupt_edges.append((p,n))\n", + " return interrupt_edges\n", + "\n", + "def _split_interrupted_branches(branches, split_edges) -> MorphTree:\n", + " for (p,n) in split_edges:\n", + " for i, branch in enumerate(branches):\n", + " if n in branch:\n", + " split_idx = branch.index(n)\n", + " branches[i:i+1] = [branch[:split_idx], branch[split_idx:]]\n", + " break\n", + " return branches\n", + "\n", "def compartmentalize(tree: MorphTree, num_comps: int = 1) -> MorphTree:\n", " branches = list_branches(tree)\n", " nodes_df = tree.to_pandas()[0].astype(float)\n", @@ -242,6 +264,7 @@ " node_attrs = nodes_df.loc[branch]\n", " xyz_i = node_attrs[[\"x\", \"y\", \"z\"]]\n", " edge_lens = ((xyz_i.diff(axis=0).fillna(0)**2).sum(axis=1)**.5)\n", + " # TODO: handle nans\n", " node_attrs[\"l\"] = edge_lens.cumsum() # path length\n", " \n", " # For single-point somatata, we set l = 2*r this ensures\n", @@ -321,6 +344,15 @@ "\n", " return MorphTree.from_pandas(nodes_df, edge_df, pd.Series(global_attrs))\n", "\n", + "def _add_missing_attrs(tree: MorphTree) -> MorphTree:\n", + " nan = float(\"nan\")\n", + " defaults = {\"id\": 0, \"x\": nan, \"y\": nan, \"z\": nan, \"r\": 1}\n", + "\n", + " for i in tree.node_attrs:\n", + " for key in set(defaults.keys()).difference(tree.node_attrs.keys()):\n", + " tree.node_attrs[i][key] = defaults[key]\n", + " return tree\n", + "\n", "# def set_solve_order(tree: MorphTree, solve_order: List[int]) -> MorphTree:\n", "# # TODO: do we want to rm branchpoints and comp_edges?\n", "# return" @@ -328,7 +360,125 @@ }, { "cell_type": "code", - "execution_count": 218, + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/tmp/ipykernel_721647/3617806162.py:32: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.\n", + " z = z0 + length * np.cos(ph) * ~(xy_only)\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxYAAAMWCAYAAABsvhCnAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAApbxJREFUeJzs3Xd41fXd//HnOTnZey+yCCNhD9kiICio7GFttVZrsXerv7auuqjetXXe1rbuet84UCkucCLI3omI7BEgzCQkZJA9zvr+/kBOSwUETpJzEl6P6+Iy5+Q73t9jznidzzIZhmEgIiIiIiLiBrOnCxARERERkbZPwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxER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dihYiIiIiJwnwzBYv3696wO3j48PV1xxBU888cQ5V7Jui+68807uvPPOM/5u5cqV37tvxowZzJgx46LP17Vr14veV7yDgoWIiIjIebBarfzjH//grbfeoqGhgaCgIP7rv/6LW2+99bRv7+XC5Ofn88Ybb5Cfn8/f//534uLi+PLLL0lNTW03LUCXCj0LRERERH5AcXExd955J6+99hoNDQ0kJyfz2muvcdtttylUuGHVqlX07NmT3Nxc5s+fT21tLQBbt27l0Ucf9XB1cqH0TBARERE5C8MwWLduHTfffDPr1q3DZDJx+eWXM2/ePPr27evp8tq8Bx54gD//+c8sWbIEPz8/1/1XXnklOTk5HqxMLoa6QomIiIicQVNTE7Nnz+bNN9+krq6OoKAgbr31Vv7rv/5LrRTNZPv27cydO/d798fFxVFWVuaBisQdChYiIiIi/6GkpITHHnuMNWvW4HA4SEpK4o9//CNDhw71dGntSkREBMeOHSMjI+O0+zdv3kxycrKHqpKLpbgtIiIi8h3DMNiwYQO33nqra+ajgQMH8u677ypUtIAbbriB+++/n+LiYkwmE06nk3Xr1nHvvfdy8803e7o8uUBqsRARERHhZNenN998kzfeeIOamhoCAwP58Y9/zG9/+1ssFn1kaglPPPEEd9xxBykpKTgcDrp164bD4eAnP/kJs2bN8nR5coH0LBEREZFLXnFxMU8++SQrV67EbreTkJDAww8/zJVXXunp0to1Pz8//vd//5dHHnmE7du3U1tbS9++fencubOnS5OLoGAhIiIilyzDMMjJyeHJJ58kPz8fi8VCv379ePLJJ+nQoYOny7tkpKSkkJKS4rp99OhRHn30UV5//XUPViUXSmMsRERE5JLU2NjI//3f/3HPPfeQn59PYGAg119/PbNnz1ao8LCKigreeustT5chF0gtFiIiInLJKSoq4i9/+QvLli3DbrcTHx/PfffdxzXXXOPp0i4Jn3766Tl/f+DAgVaqRJqTgoWIiIhcMgzDIDc3l2eeeYa9e/fi4+NDz549efzxx+nYsaOny7tkTJ48GZPJhGEYZ93GZDK1YkXSHNQVSkRERC4JDQ0NvP7669x3333k5eURGBjI5MmTef311xUqWlliYiLz58/H6XSe8d+3337r6RLlIqjFQkRERNq9wsJCnn/+eZYsWYLVaiUu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wapVq/j8889Zs2YNdrudpKQkbrjhBn72s59pJj4vVFxcTFxc3Gn3WSwWoqKizjnt709+8hPS0tJISkpi27Zt3H///eTl5TF//vyWLlk8RMFCREREWkVtbS3vvPMOS5YsYevWrQQHB5ORkcG9997LwIEDPV3eJeeBBx7g6aefPuc2u3fvvujj33777a6fe/bsSWJiIqNHjyY/P5/MzMyLPq54LwULERERaXEHDx7ko48+YteuXRQVFREVFUWfPn2YNWsWsbGxni7vknTPPfdwyy23nHObjh07kpCQwPHjx0+73263U1FRcUHjJwYNGgSc7AanYNE+KViIiIhIi3E4HKxcuZKPPvqIdevWYTabSUxMZMqUKdx+++0tuoaDnFtsbOx5hbohQ4ZQWVnJpk2bXGv3LF++HKfT6QoL52PLli0AJCYmXlS94v0ULERERKRFVFZW8sknn7By5Uq+/vprLBYLHTt25He/+x3Dhw/3dHlynrKzsxk3bhwzZ87k1VdfxWazceedd3LDDTe4ZoQqLCxk9OjRzJkzh4EDB5Kfn8/cuXO59tpriY6OZtu2bdx1111cccUVGpzfjilYiIiISLPbu3cvH3/8MStXruTo0aOEh4eTmprKc889d87pScU7vfvuu9x5552MHj0as9nMtGnTeP75512/t9ls5OXluWZ98vPzY+nSpfztb3+jrq6OlJQUpk2bxqxZszx1CdIKFCxERESk2TgcDpYvX87SpUtZs2YNjY2NJCQkMGzYMK677jqFijYqKirqnIvhpaenYxiG63ZKSgqrVq1qjdLEiyhYiIiISLM4ceIEn3zyCevXryc3N5egoCBSU1P59a9/TY8ePb43AFhE2hcFCxEREXFbXl4en332GWvWrOHgwYNERUXRuXNnHn74YdLT0ykqKvJ0iSLSwhQsRERE5KLZ7XaWLVvG6tWrWbVqFfX19cTHxzNq1CjuvvtuAgICPF2iiLQSBQsRERG5KBUVFXzyySd8/fXX5OTkEBAQQIcOHfjFL37BxIkTPV2eiLQyBQsRERG5YLt37+bzzz8nJyeHffv2ERUVRVpaGg899BBdu3b1dHki4gEKFiIiInLe7HY7S5cuZe3ataxZs4aamhoSEhIYMmQIv//97wkODvZ0iSLiIQoWIiIicl7Ky8v5+OOP2bJlC+vXr8fPz4/k5GR++tOfMmPG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7t27ycrKct0uLCxk3LhxzJgxg5kzZ55z39tvv931c8+ePUlMTGT06NHk5+eTmanXvvZIwUIumMVioVu3boSGhrJy5Uq6du2qICFtyocffsicOXOw2WyEh4dz11130b17d/7vxaPckrUSi/niw4Xx3X8dMVdispZ+NzDchmHyxRmajSNqMLaUmzRQW0Q87p577uGWW2455zanui4DFBUVMWrUKIYOHcprr1342LRBgwYBJ1s8FCzaJwULuShRUVEYhvHDG4p4kfr6ep555hlyc3MB6NKlC7NmzaKiooIbb7yR/PwDvB2dyLsza0gJrz1rq8PZGJjBbPl+9ybDqRW1RcTrxMbGEhsbe17bFhYWMmrUKPr3788bb7xxUV2bTy2OmJiYeMH7StugdzoRuSTs27ePX//61+Tm5mIymZg0aRLPPfccq1ev5uc//zn79+/H19eXoVffTOCMg9RfNhebz8nFAH8oQ7taKaKHUDcy9/tjJhQqRKQNKywsZOTIkaSmpvLss89SWlpKcXExxcXFp22TlZXF119/DUB+fj5/+tOf2LRpE4cOHeLTTz/l5ptv5oorrqBXr16euhRpYWqxEJF275NPPuH111/HarUSGhrKb3/7W3r37s2jjz7KwoULaWpqIjo6mvvuu4/x48fjcDj4YquFb7f8Ap/qrQyK2cWg1CpiAqowmwxXS4aBCWdwJo7YK9W9SUTarSVLlrB//372799Phw4dTvvdqd4LNpuNvLw816xPfn5+LF26lL/97W/U1dWRkpLCtGnTmDVrVqvXL61HwUJE2q3GxkaeffZZ1q1bB5xchPEPf/gDVVVV/OIXv2DXrl04nU66devGY489RnZ2NidOnODjjz+mqKiI/Px8fH0jsIfegD1qEFdeeSVmE2Ayc7ykmMNHjjJgwADPXqSISAu75ZZbfnAsRnp6+mldpFNSUr636ra0fwoWItIuHThwgMcff5yioiJMJhPXXnstv/zlL1m4cCHPP/88JSUl+Pr6Mm7cOB544AGioqLYt28fn332GXV1deTn5xMbG0tUVBRXXXUVl1122eknUPcmERGR0yhYiEi7s3DhQl577TWampoIDg7mzjvvZMCAATz11FN8/vnn1NbWEhkZyc9+9jN+9rOfYbFYWL58OTk5OTQ1NVFYWEhqaiqhoaFMnjyZzp07e/qSREREvJ6ChYi0G01NTfz1r391Nb+np6cza9YsGhoauOOOO9i6dSs2m41OnTpx9913c8UVV1BbW8v777/PkSNHqKuro7q6mvT0dMLCwpgxY4ZmLxERETlPChYi0i4cPnyYxx9/nKNHjwJw9dVXc8cdd7B48WJefvllCgoK8PHxYcSIEdx9991kZma6Ziqpra2ltrYWh8NBYmIisbGxzJgxg4iICM9elIiISBuiYCEibd6SJUt45ZVXaGhoIDAwkF//+tcMHjyYv/zlL3z55ZeUl5cTERHBpEmTmDlzJhEREaxbt47Vq1djGAZNTU1YLBZCQkJIT09n6tSpBAQEePqyRERE2hQFCxFps6xWKy+88AJLly4FTs5CMmvWLGw2G3fddRdbt26lvr6ejh078tOf/pTJkydjt9t5//33yc/PB8BkMmGxWPDx8aFXr15cc801+Pj4ePKyRERE2iQFCxFpkwoKCvjzn//M4cOHARg1ahS//e1vWbp0Ka+99hpHjhzBMAwGDhzIL3/5SwYOHEhRURELFiyguroak8lEYGAg9fX1ri5SQ4cOxWS6kLW2RURE5BQFCxFpc1asWMGLL75IfX09AQEB3H777QwfPpznn3+eRYsWcfz4ccLCwrjyyiv5+c9/Tnp6Ops2bWLZsmU4HA6Cg4Px8fGhuroaHx8frrvuOnr06OHpyxIREWnTFCxEpM2w2+28/PLLLFq0CMMwSEpKYtasWTgcDu677z62b99OVVUVqampjB8/nh//+McEBgby8ccfs3v3bgCSk5Oprq6murqawMBApk6dSlpamoevTEREpO1TsBCRNuHYsWM8/vjjrrERw4cP53e/+x2rVq1i9uzZHD58GJvNRv/+/Zk8eTLXXXcdJ06cYN68eVRUVGA2m+nRowd79+6lsbGRiIgIfvSjHxEdHe3hKxMREWkfFCxExOutXbuWv//979TW1uLn58cvfvELRo0axcsvv8zSpUspLi4mKCiIkSNHcv3113PZZZexfft2Fi9ejM1mIywsjG7durFx40YcDgfJyclMnz6d4OBgT1+aiIhIu6FgISJey+Fw8Nprr/HZZ59hGAYJCQk8/PDDADz44IPs2LGDiooKkpKSGDlyJDfccANJSUl8+eWXbNmyBYCOHTsSFxdHTk4OAF27dmXixIn4+vp66rJERETaJQULEfFKpaWl/OlPf2Lfvn0ADB48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jJxOZ6XH9Pb21pw5czRx4kTdddddzBrlJswKBQAAgFoTFxenuLg4SWUDucvXmThx4oSksq5RgwYNklTWNWrfvn1q166dli9frpdeekmPPPKIvLy89PXXX8sYo44dOyomJkanT5/WP//5TyUmJiohIUERERFasWKFxowZo9LSUoWHh7vKEBYWpgEDBuj111+XJGaNqicECwAAANSJqVOnauzYserfv7/atWsnqequUe3bt1dBQYHuuOMO1/bt27dXUFCQgoKCFBMTow4dOujf//63ZsyYoY8//liS1LZtW40YMcJ1XLvdroCAAIWFhdXr673cMcYCHmPu3LmKiYlRSEiIQkJCNGjQIH3xxRdV7rN48WJ17dpV/v7+6tWrlz7//PN6Kq1nePbZZzVgwAAFBwerZcuWGj16tNLS0qrcZ/78+bLZbBVu/v7+9VRi97uUOpM411avXq2bbrpJERERstlsF+27/O233553ntlsNmVmZtZPgT1ATetMKqu3vn37ys/PT506ddL8+fPrvJye6JVXXlG7du3k7++v2NhY17Sklbncr2nlalJnUv1d026//XbNnj1bjz32mK6//npJ0vTp09WqVSsVFxfr5MmTstlsrgAwb948SdKCBQsUHh7uus2ePVuS5O/vLz8/P33wwQeKjo7WsmXLJElvvfVWhVaJo0ePatmyZerSpYsmTZp0wcX9ULsIFvAYkZGRmjlzprZs2aLNmzfr17/+tW6++Wbt2LGj0u0TExP1hz/8QePHj9e2bds0evRojR49WqmpqfVccvdJSEjQ5MmTtX79en399dcqKSlxzQVelZCQENfsGhkZGTpw4EA9ldj9LqXOONekvLw8XXHFFXrllVdqtF9aWlqFc61ly5Z1VELPU9M627dvn0aNGqVrrrlGSUlJuu+++zRhwgR9+eWXdVxSz/Lhhx9q6tSpmjFjhrZu3aorrrhCI0aM0LFjxy64z+V8TZNqXmf1fU2Li4vTgQMHVFxcrIEDB1bZNWr//v26//77NXDgQNcsUcYYPf7445LKZp4KDQ3VX/7yF61Zs0alpaVq2rSpkpKSXMcbOnSobDabHn/8cc2aNUsJCQm64YYb5HA46uT14SwG8GBNmjQxb775ZqWP3XbbbWbUqFEV7ouNjTUTJ06sj6J5pGPHjhlJJiEh4YLbvP3226Zx48b1VygPV50641yrSJL55JNPqtxm1apVRpI5depUvZTJ01Wnzh544AHTo0ePCvfdfvvtZsSIEXVYMs8zcOBAM3nyZNfvDofDREREmGeffbbS7bmm1bzO3HlNW7RokfHz8zPz58833377rZFkgoKCTGZmpjHGmDFjxpjY2FgzcOBAY4wxTzzxhPnyyy9Nenq62bJli/n9739v/P39zY4dO8y9995revXqZWbOnGlCQ0PN0qVLTXJysrn55ptN+/btTUFBgTHGmPT0dCPJrFixos5f3+WOFgt4JIfDoUWLFikvL8/1Lca51q1bp+uuu67CfSNGjNC6devqo4ge6fTp05Kkpk2bVrldbm6u2rZtq6ioqCpbhS4H1akzzrVL17t3b4WHh+v666/X2rVr3V0cj8Z5VrbA2pYtWyrUg91u13XXXVdlPVzO17RLqTN3nmtVdY2SpB9//FEnTpxwdY06deqU7rnnHnXr1k0jR45UTk6OEhMT1bZtWy1atEjjx4/XAw88oL/+9a+69957NWDAAOXm5io+Pt7VJa5Dhw5q3ry59u7dW+ev73JHsIBHSUlJUVBQkPz8/PTnP/9Zn3zyibp3717ptpmZma4LUblWrVpdVn24z+Z0OnXfffdpyJAh6tmz5wW369Kli/7zn/9o6dKlev/99+V0OjV48GAdOnSoHkvrGapbZ5xrNRceHq7XXntN//3vf/Xf//5XUVFRGjZsmGuxK5zvQudZTk6OCgoK3FSq+nXixAk5HI4avd8u92vapdSZu69pF+oaJUkrV65UYWGh60vFF198UQcOHFBRUZEyMzP12WefqU+fPlq8eLGKior0pz/9STabTU8++aQyMzNVWFioFStWKDo62vWchw4d0smTJyvMGoW6waxQ8ChdunRRUlKSTp8+rSVLlmjs2LFKSEi4YLjAzyZPnqzU1FStWbOmyu0GDRpUoRVo8ODB6tatm+bNm6ennnqqrovpUapbZ6i5Ll26qEuXLq7fBw8erPT0dL344ot677333Fgy/NJwTWvYzp41auDAgXrppZeUl5fnmjXqzjvvVOvWrfXss89W2O+tt97S6NGj1axZswr35+bm6oknntCtt96qsLAwpaen64EHHlCnTp0qzBqFukGwgEfx9fVVp06dJEn9+vXTpk2b9PLLL7tmiThbWFiYjh49WuG+o0ePXpZTy8XFxWn58uVavXq1IiMja7Svj4+P+vTpc9k1EdekzjjXasfAgQMJcVW40HkWEhKigIAAN5WqfjVv3lxeXl6W3m+X2zXtUurMk65pt99+u44fP67HHntMmZmZ6t27t+Lj4yt0jbLbK3awSUtL05o1a/TVV1+d93xeXl5KTk7WO++8o+zsbEVERGj48OF66qmnWMuiHtAVCh7N6XSqqKio0scGDRqkb775psJ9X3/99QXHZPwSGWMUFxenTz75RCtXrlT79u1r/BwOh0MpKSmXTRPxpdQZ51rtSEpKumzOs0vBeVb25VK/fv0q1IPT6dQ333xT7Xq43K5pl1JnnnaulXeNKioq0oYNGxQbG+t67Ntvvz1v2uUuXbrIGOMao3G2gIAAffnllzp27JiKi4u1f/9+vf766+d1/UIdcfPgccDloYceMgkJCWbfvn0mOTnZPPTQQ8Zms5mvvvrKGFM2U8RDDz3k2n7t2rXG29vbzJ492+zatcvMmDHD+Pj4mJSUFHe9hHo3adIk07hxY/Ptt9+ajIwM1y0/P9+1zbn1VtUMG5eDS6kzzjVjzpw5Y7Zt22a2bdtmJJkXXnjBbNu2zRw4cMAYU/b+HTNmjGv7F1980Xz66admz549JiUlxUyZMsXY7fbLalaWmtbZDz/8YAIDA839999vdu3aZV555RXj5eVl4uPj3fUS3OLsWYN27txp7r33XhMaGlph1iCuaRXVtM64pqGuECzgMe6++27Ttm1b4+vra1q0aGGuvfZaV6gwxpirr77ajB07tsI+H330kYmOjja+vr6mR48e5rPPPqvnUruXpEpvb7/9tmubc+vtvvvuM23atDG+vr6mVatWZuTIkWbr1q31X3g3uZQ6M4ZzrXz62HNv5fU0duxYc/XVV7u2nzVrlunYsaPx9/c3TZs2NcOGDTMrV650T+HdpKZ1Vr5P7969ja+vr+nQoUOF8/Jy8u9//9t1nRo4cKBZv3696zGuaZWrSZ0ZwzUNdcNmjDH11z4CAAAA4JeIMRYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwLL/D4PrqESWqjIiAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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mqlTp1K9enVHl1ai6TaoiIiIMGfOHCZMmMDp06eZOHEiL774Ys7VneIw+e+2KiIiIi7n2LFjTJgwgdmzZzNo0CBiYmKoX7++o8uSK+g2qIiISAmUmZnJxx9/TNOmTdmwYQO///47UVFRCmpOSCNrIiIiJczKlSt57LHHiI2NZcKECbz99tv4+fk5uizJg0bWRERESohz587x4IMP0rNnT8qUKcOmTZv4/PPPFdScnEbWREREXJzVauXHH3/kpZdewmq18t133/Hwww/b20WJc9P/JRERERe2Y8cOevbsycMPP0xwcDB79+7l0UcfVVArRvR/SkRExAUlJyfz/PPP07ZtW+Lj41myZAk//fQTVatWdXRpcpN0G1RERMSFGIbBrFmzmDBhAufPn+fdd9/lueeew8vLy9GlyS3SyJqIiIiLOHz4MEOHDmXUqFG0bt2aXbt28corryioFXMKayIiIsVcRkYGH3zwAc2bN2fbtm3MmDGDuXPnUrduXUeXJgVAt0FFRESKsaVLl/L444+zb98+nnnmGd588018fX0dXZYUII2siYiIFENxcXHcf//99O3blwoVKrB582Y++eQTBTUXpJE1ERGRYsRqtfLf//6Xl19+GTc3N77//nvGjRunrThcmP7PioiIFBNbtmyhW7dujB8/npEjR7J3714eeughBTUXp/+7IiIiTi4pKYlnnnmGDh06kJyczIoVK/jxxx+pXLmyo0uTIqDboCIiIk7KMAwsFgtPP/00Fy9e5MMPP+Tpp5/G09PT0aUVHsMKJo0lXUlhTURExAkdPHiQf/zjHyxYsIARI0bwxRdfUKdOHUeXVfAubIZDkyFuBSTGgjUT3DzBrxlU7Qn1xkHFdo6u0qFMhmEYji5CREREbNLT0/noo494//33qV69Ol999RVDhw51dFkFL+kArH0Izi4HkwcYWdcec/nxKr2gyw9QtkHR1+kEFNZEREScRExMDI8//jiHDh3iueee4/XXX6dMmTKOLqvgHZkGax8EIzv3kHY1kweY3KHLZPC/p/DrczIKayIiIg52+vRpnnvuOaZNm0avXr3417/+RfPmzR1dVqFI3vUjn7z+EOsOwvqDEJ8Ckx+BB3rnPO6B7+CnFde+vnG9Guw5eLJoinUSmrMmIiLiINnZ2Xz33XdMnDgRT09PpkyZwv3334/JZHJ0aYUjcT/n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kp2dzYoVK+wB7fTp09SqVcse0Lp166aA5oIU1kRExKVlZmby+eef8/bbb1O+fHnCw8MZPXp0sdkzLSsri2XLlmGxWJgxYwZxcXHUrl2be+65B7PZTJcuXXBz0wpKV6bboCIi4rJWrFjBY489xu7du3nqqad4++23KVu2rKPLuqHMzEyWLFlCeHg4M2fO5Pz58/j7+xMSEoLZbKZjx47FJmzK7dPImoiIuJyzZ8/y4osvMmXKFLp06cKmTZto06aNo8u6royMDGJiYggPD2fWrFnEx8dTv359Hn74YcxmM+3atVNAK6E0siYiIi7DarXy448/8tJLL2EYBh9++CF///vfnfY2YXp6OgsXLsRisTB79mwSEhJo1KiRfQStdevWCmiisCYiIq5h+/btjB8/njVr1nD//ffzySefULVqVUeXdY1Lly6xYMECLBYLc+bMISkpiWbNmmE2mzGbzbRo0UIBTXLQbVARESnWkpOTeeutt/jnP/9Jo0aNWLp0Kb1793Z0WTmkpqYyb948LBYLERERJCcn07JlS55//nnMZjPNmjVzdInixDSyJiIixZJhGMycOZOnnnqK8+fP88Ybb/Dss886Tfuk5ORkoqKisFgsREZGkpqaSps2bQgJCWH06NE0btzY0SVKMaGwJiIixc7hw4d54okniIqKIjg4mK+++gp/f39Hl0VSUhIRERGEh4czb9480tLS6NChA2azmdGjR9OgQQNHlyjFkMKaiIgUGxkZGXz66ae8++67VKlShS+//JLhw4c7dI5XQkICc+fOJTw8nAULFpCenk7nzp3tAa1u3boOq01cg8KaiIgUC0uXLuWxxx5j//79PPPMM7z55pv4+vo6pJb4+Hhmz56NxWJh4cKFZGZm0rVrV/stzjp16jikLnFNCmsiIuLU4uLieP755/n555/p3r073377LS1btizyOs6fP8+sWbOwWCxER0eTnZ1Njx497CNotWrVKvKapGRQWBMREadktVr5z3/+wyuvvIK7uzsff/wxDzzwQJHumRYXF2cPaIsXL8YwDHr16kVISAgjR46kRo0aRVaLlFwKayIi4nS2bNnC+PHjWb9+PQ8++CAfffQRlStXLpL3Pn36NDNnzsRisbB06VJMJhN9+vQhJCSEESNGUK1atSKpQ+Qy7bMmIiJOIzExkddff52vv/6aZs2asWLFCnr0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3Xf89ttvNGvWjFmzZjm6LBERuYrCmkgJ5ubmxqOPPkpsbCzt27dn5MiR3HXXXZw5c8bRpYmIyJ8U1kSEO+64gzlz5vDLL7+wZMkSmjZtyv/+9z+1rBIRcQIKayIC2FpW3X333ezevZshQ4bwt7/9jcGDB3P06FFHlyYiUqIprIlIDpUrVyYsLIyIiAh27dpF8+bN+eqrr7BarY4uTUSkRFJYE5FcBQUFsWvXLu6//34mTJhAz5492b17t6PLEhEpcRTWRCRPfn5+/Otf/2LZsmWcPXuWNm3aMGnSJDIzMx1dmohIiaFNcUUkXy5dusQ777zDJ598QvPmzfnxxx9p3769o8sSEXF5GlkTkXwpVaoUH3zwAevXr8fNzY1OnTrx4osvqmWViEgh08iaiNy0zMxMPv30U95++21q167Nf//7X/r06ePoskREXJJG1kTkpnl6evLKK6+wdetWqlWrRt++fRk/fjwJCQmOLk1ExOUorInILWvSpAnLly/nm2++YerUqTRv3py5c+c6uiwREZeisCYit8XNzY3HH3+cXbt20apVK4YNG8Y999xDXFyco0sTEXEJCmsiUiDq1KlDZGQkP//8M4sWLaJZs2ZMnTpVLatERG6TwpqIFBiTyURoaCixsbH079+f0NBQgoODOX78uKNLExEpthTWRKTAVa1alV9++YXZs2ezdetWmjVrxr/+9S+1rBIRuQUKayJSaIYNG0ZsbCxjx47lH//4B3369GHv3r2OLktEpFhRWBORQlWuXDn+/e9/s3jxYk6ePEnr1q358MMP1bJKRCSfFNZEpEj07duX7du3M2HCBCZOnEinTp3YsmWLo8sSEXF6CmsiUmRKly7Nxx9/zLp168jOzqZjx4688sorXLp0ydGliYg4LbWbEhGHyMjI4OOPP+bdd9/F39+f77//np49ezq6LBERp6ORNRFxCC8vL1577TW2bNlCpUqV6NWrF//4xz9ITEx0dGkiIk5FYU1EHKpZs2asWLGCL774gilTptC8eXOioqIcXZaIiNNQWBMRh3N3d2fChAns2rWLZs2aERQURGhoKOfOnXN0aSIiDqewJiJOw9/fn/nz5zNlyhSioqJo2rQpv/76q1pWiUiJprAmIk7FZDLxt7/9jdjYWPr06cM999zD8OHD+eOPPxxdmoiIQyisiYhTql69OuHh4cyYMYMNGzbQvHlz/v3vf6tllYiUOAprIuLURo4cSWxsLCEhIYwfP55+/fqxf/9+R5clIlJkFNZExOlVqFCB77//nkWLFnHs2DFatWrFJ598QlZWlqNLExEpdAprIlJsBAYGsmPHDh577DFefvllunTpwrZt2xxdlohIoVJYE5FipUyZMvzf//0fq1evJi0tjQ4dOvD666+Tnp7u6NJERAqF2k2JSLGVkZHBBx98wKRJk6hfvz7ff/893bt3d3RZIiIFSiNrIlJseXl58eabb7J582b8/Pzo2bMnEyZMIDk52dGliYgUGIU1ESn2WrRowerVq/nss8/44YcfaN68OQsWLHB0WSIiBUJhTURcgru7O8888ww7duygYcOGDBo0iL/97W+cP3/e0aWJiNwWhTURcSn16tVj0aJF/PDDD8yePZtmzZoRHh6ullUiUmwprImIyzGZTDz44IPExsbSrVs37rrrLkaNGsXJkycdXZqIyE1TWBMRl1WzZk1mzJhBeHg4q1evplmzZnz//fcaZRORYkVhTURcmslkwmw2s3v3bkaOHMnDDz9MYGAgBw8edHRpIiL5orAmIiVCxYoVmTx5MgsWLODgwYO0bNmS//u//yM7O9vRpYmIXJfCmoiUKAMGDGDnzp08/PDDPP/883Tr1o2dO3c6uiwRkTwprIlIiePr68sXX3zBypUrSUxMpF27drz55ptqWSUiTkntpkSkREtPT2fSpEl88MEHNGrUiB9++IEuXbo4uiwRETuNrIlIiebt7c0777zDpk2bKF26NN26deOZZ54hJSXF0aWJiAAaWRMRscvKyuKf//wnr7/+OtWrV+e///0vgYGBji5LREo4jayJiPzJw8OD559/nh07duDv70///v156KGHiI+Pd3RpIlKCKayJiFylQYMGxMTE8J///AeLxUKzZs2YMWOGo8sSkRJKYU1EJBdubm48/PDDxMbG0qlTJ0aPHo3ZbOb06dOOLk1EShiFNRGR66hVqxazZs3it99+Y/ny5TRt2pQpU6aoZZWIFBmFNRGRGzCZTNx1113s3r2boUOHMm7cOAYOHMjhw4cdXZqIlAAKayIi+VSpUiX+97//ERUVxZ49e2jRogVffPGFWlaJSKFSWBMRuUmDBw9m165djBs3jqeffpoePXoQGxvr6LJExEUprImI3IKyZcvy9ddfs2LFCuLj42nbti3vvPMOGRkZji5NRFyMNsUVEblNaWlpvPvuu3z00Uc0bdqUH3/8kY4dOzq6LBFxERpZExG5TT4+PkyaNImNGzfi6elJly5deP7550lNTXV0aSLiAjSyJiJSgLKysvjss8948803qVWrFt9//z19+/Z1dFkiUoxpZE1EpAB5eHjw0ksvsX37dmrVqkW/fv145JFHuHjxoqNLE5FiSmFNRKQQNGrUiKVLl/Ltt9/y66+/0rx5c2bPnu3oskSkGFJYExEpJG5ubowfP55du3bRtm1bRowYwZgxYzhz5oyjSxORYkRhTUSkkNWuXZu5c+cydepUYmJiaNasGT///LNaVolIviisiYgUAZPJxNixY9m9ezeDBg3i/vvvZ8iQIRw9etTRpYmIk1NYExEpQlWqVGHq1KnMnTuXHTt20KJFC7755husVqujSxMRJ6WwJiLiAMHBwcTGxhIaGsoTTzxBr1692LNnj6PLEhEnpLAmIuIgfn5+fPvttyxdupS4uDhat27N+++/T2ZmpqNLExEnok1xRUScwKVLl3j77bf59NNPadGiBT/88APt27d3dFki4gQ0siYi4gRKlSrFhx9+yLp16wDo3LkzL730EpcuXXJwZSLiaAprIiJOpH379mzYsIF33nmHL774gtatW7Ns2TL781arlXfffZcdO3Y4sEoRKUoKayIiTsbT05NXX32VrVu3UrVqVfr06cNjjz1GYmIi33//PW+88Qb33HMP2dnZji5VRIqA5qyJiDgxq9XKt99+y8svv4yvry/x8fGkp6cD8M033/D444/n70SGFUz6+VykOFJYExEpBo4cOULHjh05d+6c/TE/Pz8OHTpEpUqVrn3Bhc1waDLErYDEWLBmgpsn+DWDqj2h3jio2K4IP4GI3Cr9mCUiUgysXbs2R1ADSE5OZuLEiTkPTDoAi3rD/Paw/zu4uM0W1MD268Vttsfnt7cdl3SgiD6BiNwqjayJiBQDDRo04ODBg3h6el6zD9uiRYsIDAyEI9Ng7YNgZIORdeOTmjzA5A5dJoP/PYVUuYjcLoU1EZFiYNmyZaxevZrjx49z/PhxDh8+zJEjR0hJSSEkJITfPx4Bq0OBvL+kT5oFr4VD8ztg50dXPmOCbmHgP7ZwP4SI3BKFNRGRYiw9PR3v9GMQ1RKs6Xke98d5aPwCmAD/KleHNcDNG4J2QtkGhVqviNw8zVkTESnGvL29Yd3fbbc+r+P5adClAXSol8cBRjasfajgCxSR26awJiJSnF3YBGeXX3eO2vLdYFkP/wy9znmMLNt5Lmwu+BpF5LYorImIFGeHptgWCuQh2wpP/g/+3gda1rnBuUwetu0+RMSp5P0vXEREnF/ciuuOqn0XDUfPQfQr+TiXkQVxKwuuNhEpEBpZExEpzhJj83zqfBK8MR1eHwFV/PJ7vl0FUpaIFByFNRGR4sqw/rXhbS5eC4eKZeDJgTdxTmum7bwi4jR0G1REpLgyudlaSOUS2Pafhv8shn/eByfj/3o8LQMys+HIWfArBRV9r3qhm6d6iIo4Ge2zJiJSnEW1sbWQusrSWOg76fovfWqQLcxd6Y+UKpxpN4927dphMpkKrk4RuWUaWRMRKc6q9oSEXdcsMmhRG2Y+c+3hr4VD0iX44n6oXzXnc9mGGws2J/P3RzrQpEkTQkNDuffee/H39y+8+kXkhjSyJiJSnF3YbGvKnk993oNzSbl0MPhTVv91xGyOJywsjBkzZpCamkqPHj247777CAkJoUKFCgVUuIjklyYmiIgUZxXbQZVe191rLT8MkwdU6YVHlU4MHDiQn3/+mTNnzhAWFoavry+PPfYY1atXZ9SoUcyYMYP09LxbW4lIwdLImohIcZd0ACJbXLc36PVYDcg23PEYthuTX8Ncjzl9+jS//fYbYWFhbNy4kfLlyxMSEkJoaCg9evTAzU0/+4sUFoU1ERFXcOQXWH0vcPNf0g0Dxn4Dldr9gy+//PKGwWvPnj1MnTqVsLAwjhw5Qp06dbj33nsJDQ2lWbNmt/gBRCQvCmsiIq7iyDRY+6CtKft1uhrYmTzA5A5dJvPfRck8+uij/P3vf+e7777L10iZ1Wpl9erVhIWF8fvvvxMfH0+7du0IDQ3l7rvvpkaNGgXwoUREYU1ExJUkHYC1D9masps8cg9tlx+v2hs6fw9lGwDw008/MW7cOO6//35++OEH3N3d8/226enpzJs3j7CwMObOnUtWVhaBgYGEhoYycuRIfH2v3tBNRPJLYU1ExBVd2Gxryh630tZCyppp2/DWrzlU7QH1xtkWJ1xl2rRp3H///YwZM4affvoJD4+bX7gQHx/P9OnTCQsLY9myZZQuXZoRI0YQGhpK//79b+mcIiWZwpqISElgWPPdmcBisXDPPfcwYsQIpk2bhqen5y2/7dGjR/nll1/4+eefiY2NpWrVqtx9992EhobSoUMHbbwrkg8KayIico3Zs2cTEhLCkCFD+O233/D29r6t8xmGwdatWwkLC2PatGmcPn2aRo0a2TferVevXgFVLuJ6FNZERCRXUVFRjBo1ioCAAKZPn46Pj0+BnDc7O5vFixcTFhbG9OnTSUlJoXv37oSGhhISEkKlSpUK5H1EXIXCmoiI5GnRokUMHz6cHj16MGvWLEqXLl2g509JSWHOnDmEhYWxYMEC3NzcGDJkCKGhoQQHBxdYQBQpzhTWRETkupYuXUpwcDAdO3Zk7ty5hbayMy4ujt9++42ff/6ZDRs2UK5cOcxmM6GhofTq1Usb70qJpbAmIiI3tGrVKgYPHkyrVq2IiorCz8+vUN9v79699o13Dx8+TO3atRk7diz33XcfzZs3L9T3FnE2CmsiIpIv69atY+DAgTRp0oT58+dTvnz5Qn9PwzBYs2YNYWFh/Pbbb1y4cIE2bdoQGhrKPffcQ82aNQu9BhFHU1gTEZF827RpEwMGDMDf359FixZRsWLFInvvjIwM5s+fT1hYGHPmzCEjI4OAgABCQ0MZNWoUZcuWLbJaRIqSwpqIiNyUbdu2ERgYSM2aNYmOjqZKlSpFXkNCQoJ9492lS5fi4+PD8OHDCQ0NZcCAAbe1N5yIs1FYExGRm7Zr1y4CAgKoVKkSMTExVK9e3WG1HD9+nGnTpvHzzz+za9cuqlSpYt94t2PHjtp4V4o9hTUREbkle/fupV+/fvj6+rJ48WJq1arl0HoMw2D79u32jXdPnjxJw4YN7Rvv1q9f36H1idwqhTUREbllBw4coF+/fnh5ebF48WLq1Knj6JIA28a7S5cuJSwsDIvFQnJyMl27diU0NJS77rqLypUrO7pEkXxTWBMRkdty5MgR+vXrh2EYLF68mLp16zq6pBxSU1OZO3cuYWFhzJ8/H4DBgwcTGhrK0KFDKVWqlIMrFLk+hTUREbltx48fp1+/fqSlpbF48WIaNmzo6JJydfbsWX777TfCwsJYt24dZcuWtW+827t3b9zd3R1dosg1FNZERKRAnDx5koCAABISEli8eDFNmjRxdEnXtX//fvvGuwcPHqRWrVrce++9hIaG0rJlS0eXJ2KnsCYiIgXmzJkzBAYGEhcXR0xMDC1atHB0STdkGAbr1q0jLCyMX3/9lfPnz9OqVSv7xrt33HGHo0uUEk5hTURECtS5c+fo378/x48fJzo6mjZt2ji6pHzLyMhg4cKF/Pzzz8yZM4f09HT69u1LaGgoo0ePLvQ2WyK5UVgTEZECd+HCBQYOHMjBgwdZuHAhHTp0cHRJNy0hIYEZM2YQFhbGkiVL8Pb2ZtiwYYSGhjJo0CBtvCtFRmFNREQKRUJCAoMGDSI2NpYFCxbQpUsXR5d0y/744w9++eUXwsLC2L59O5UqVbJvvNu5c2dtvCuFSmFNREQKTVJSEkFBQWzZsoWoqCh69uzp6JJu2/bt25k6dSpTp07lxIkT1K9f377xrrOugpXiTWFNREQKVUpKCkOHDmXdunXMnTuXfv36ObqkApGdnc3y5cvtG+8mJibSuXNnQkNDGTNmjEN6poprUlgTEZFCl5qaysiRI1m+fDmzZ89mwIABji6pQF26dMm+8e68efMwDINBgwYRGhrKsGHDKF26tKNLlGJMYU1ERIpEWloaZrOZRYsWMWPGDIKCghxdUqE4d+4cv//+O2FhYaxZs4ayZcsyevRoQkND6dOnjzbelZumsCYiIkUmIyODu+++m4iICH777TdGjhzp6JIK1cGDB+0b7+7fv5+aNWsyduxYQkNDadWqlRYmSL4orImISJHKzMwkNDSU6dOnM23aNO666y5Hl1ToDMNgw4YNhIWF8csvv3Du3DlatGhBaGgoY8eOpXbt2o4uUZyYwpqIiBS5rKwsxo0bx7Rp0/jf//7Hvffe6+iSikxmZiYLFy4kLCyMWbNmkZ6eTu/eve0b75YvX97RJYqTUVgTERGHyM7O5uGHH2bKlCn88MMPjBs3ztElFbnExERmzpxJWFgYMTExeHl5MXToUEJDQxk8eDBeXl6OLlGcgMKaiIg4jNVq5fHHH+ff//433333HY8++qijS3KYEydO8OuvvxIWFsbWrVupWLEiY8aMITQ0lK5du2p+WwmmsCYiIg5lGAZPPfUUX331FV9++SVPPvmko0tyuJ07d9o33j1+/Dh169a1b7zbuHFjR5cnRUxhTUREHM4wDF588UU+/fRTPv30U5577jlHl+QUrFarfePd8PBwEhMT6dixI6Ghodx9991UrVrV0SVKEVBYExERp2AYBq+//jqTJk1i0qRJvPrqq44uyamkpaURERFBWFgYUVFRWK1WBgwYQGhoKMOHD6dMmTKOLlEKicKaiIg4lXfeeYc333zT/p/mal3r/PnzhIeHExYWxqpVqyhTpgyjRo0iNDSUgIAAbbzrYhTWRETE6Xz44Ye88sorvPLKK0yaNEmB7ToOHTpk33h33759VK9e3b7xbps2bfR35wIU1kRExCl9/vnnPPvsszz77LN8+umnCh03YBgGGzdutG+8e/bsWZo1a2bfePfOO+90dIlyixTWRETEaX3zzTc88cQTPPHEE3zxxRe4ubk5uqRiITMzk+joaMLCwpg5cyaXLl2iV69ehIaGYjabqVChgqNLlJugsCYiIk7tv//9L48++igPP/ww3377rQLbTUpKSmLWrFmEhYURHR2Nh4cHwcHBhIaGMmTIELy9vR1dotyAwpqIiDi9KVOm8OCDD/K3v/2N77//XhPob9GpU6f45ZdfCAsLY8uWLZQvX5677rqL++67j27duhVNEDasYFLgvhkKayIiUixMmzaN+++/nzFjxvDTTz/h4eHh6JKKtV27dtk33j127Bj+/v7ce++9hIaG0qRJkzxfl5aWho+PT/7f6MJmODQZ4lZAYixYM8HNE/yaQdWeUG8cVGxXAJ/IdSmsiYhIsREeHs7YsWMZOXIkU6dOxdPT09ElFXtWq5WVK1cSFhbG77//TkJCAu3bt7dvvFu9enX7sXFxcTRo0ICHH374xos+kg7A2ofg7HIweYCRde0xlx+v0gu6/ABlGxTCJyz+FNZERKRYmT17NiEhIQQFBfHrr79qzlUBSktLIyoqirCwMCIiIsjOzqZ///6EhoYyYsQIfvzxR5566ikA3njjDd5+++3cT3RkGqx9EIzs3EPa1UweYHKHLpPB/54C/ESuQWFNRESKnaioKEaNGkVAQADTp0+/udtyki8XLlywb7y7cuVKSpcujbe3N/Hx8fZjPv74Y1544QX7n5OTk/lk4v2sWzqT9QchPgUmPwIP9M557vUHYcpyWHcAth+HrGwwpgKYoFsY+I8tmg9ZTGiGn4iIFDtDhgxh7ty5LFmyhGHDhpGamuroklxOxYoVefTRR1mxYgWHDh3i4YcfzhHUAF588UW++eYb+5/PHd7AO1/OZPcJaF0n73NHbYXvl4DJBPVytDc1bCNySQcK9LMUdwprIiJSLPXv35+oqChWr15NUFAQycnJji7JZdWtWxc/P79cV4s+8cQTvPfeewDUOPYGp/7lztEv4ZPrDI49FggJ38PG96B/i6ueNLJtc93ETmFNRESKrT59+jB//nw2bdrE4MGDSUxMdHRJLmvGjBlYrdYcj5UuXZry5cuTlpYGFzbhnbCS6uWyb3iuauWglFceTxpZtkUJFzYXQNWuQeueRUSkWOvRoweLFi1i4MCBDBgwgPnz51O+fHlHl+VyPvzwQ06cOMGdd95JnTp1qFOnDr6+vn8dsPHJvFd93iyTh227D23pASisiYiIC+jcuTMxMTEMGDCAwMBAFi5cSMWKFR1dlksJDg6+/gFxKwomqIHtPHErC+ZcLkC3QUVExCW0b9+exYsXc/ToUfr168fZs2cdXVLJkhhbwOfbVbDnK8YU1kRExGW0bt2apUuXcvr0afr27cvp06cdXVLJYFhtnQkKkjXTdl5RWBMREdfSvHlzli1bRnx8PH369OHEiROOLsn1mdxsLaQKkpuneoj+SX8LIiLicho3bsyyZctITU2ld+/eHDt2zNEluT6/ZgV8vuYFe75iTGFNRERcUoMGDVi+fDnZ2dn07t2bw4cPO7ok11a1p20VZ0EweUDVHgVzLhegdlMiIuLSjh8/Tr9+/UhPT2fx4sU0aKBm4YXiwmaY356vF8LFFDh5Eb6NhlEdoe2dtkOeHAjlSsPRs/Dzn4s9I7bAuoPwrtn25zsrw309gUGbtHXHnxTWRETE5Z08eZKAgAASEhJYvHgxTZo0cXRJrmlRb/zHLufoudyfPvxP8K8CS2Oh76Tcj+ndFJZ+0Qv6Lyu0MosbhTURESkRzpw5Q0BAAOfOnSM6OpoWLa7ucyS3LekARLYAa/qtn8PNG4J2QlmNgF6mOWsiIlIiVKtWjSVLllC9enX69u3Ltm3bHF2S6ynbALpMBky3eAKT7fUKajkorImISIlRpUoVFi9ejL+/P3379mXjxo2OLsn1+N8D3cJsI2T5XXBg8rAd322q7fWSg26DiohIiZOQkMCgQYOIjY1lwYIFdOnSxdEluZ6kA7D2IVtT9rx6hl5+vGpv6Py9RtTyoLAmIiIlUlJSEkOGDGHr1q3MmzePHj20VUShuLDZ1pQ9bqWthZQ107bhrV9z2/Yc9cZp1ecNKKyJiEiJlZKSwtChQ1m3bh0RERH07dvX0SW5PsOqzgQ3SX9bIiJSYpUpU4aIiAh69OjBkCFDWLhwoaNLcn0KajdNf2MiIlKilS5dmtmzZxMQEMCwYcOIiopydEkiOSisiYhIiefj48OMGTMYPHgwI0aMYNasWY4uScROYU1ERATw8vLi999/Z+TIkYSEhBAeHu7okkQAhTURERE7T09Ppk6dyt13383dd9/N1KlTHV2SCPncrU5ERKRk8PDwYMqUKXh6enLfffeRmZnJAw884OiypARTWBMREbmKu7s733//PV5eXowbN46MjAweeeQRR5clJZTCmoiISC7c3Nz49ttv8fLy4tFHHyUjI4MnnnjC0WVJCaSwJiIikgeTycQXX3yBt7c3Tz75JBkZGTz77LOOLktKGIU1ERGR6zCZTHz88cd4eXnx3HPPkZ6eziuvvOLosqQEUVgTERG5AZPJxHvvvYe3tzevvvoqGRkZvPHGG5hMJkeXJiWAwpqIiEg+mEwm3njjDby8vHjllVdIT09n0qRJCmxS6BTWREREbsLLL79svyWakZHBJ598osAmhUphTURE5CY9++yzeHl52RcdfPHFFwpsUmgU1kRERG7BE088gZeXF+PHjyc9PZ1vv/0WNzc1BpKCp7AmIiJyix555BG8vLx48MEHycjI4Pvvv8fd3d3RZYmLUVgTERG5DQ888ABeXl7cd999ZGRk8NNPP+HhoW+vUnB0NYmIiNymsWPH4unpydixY8nMzGTq1Kl4eno6uixxESbDMAxHFyEiIuIKZs+eTUhICEFBQfz66694e3s7uiRxAQprIiIiBSgqKopRo0YREBDA9OnT8fHxcXRJUswprImIiBSwRYsWMWzYMHr27MmsWbMoXbq0o0uSYkxhTUREpBAsWbKE4OBgOnfuzNy5cylTpoyjS5JiSmFNRESkkKxcuZIhQ4bQunVrIiMj8fPzc3RJUgwprImIiBSitWvXMmjQIJo2bcq8efMoX768o0uSYkZhTUREpJBt2rSJ/v37U69ePRYuXEjFihUdXZIUIwprIiIiRWDbtm0EBgZSq1YtFi1aRJUqVRxdkhQTCmsiIiJFZNeuXQQEBFC5cmWio6OpXr26o0uSYkBhTUREpAjt3buXfv36UbZsWRYvXkzNmjUdXZI4OTdHFyAiIlKSNG7cmGXLlpGamkrv3r05fvy4o0sSJ6ewJiIiUsQaNGjA8uXLycrKolevXhw+fNjRJYkTU1gTERFxAH9/f5YvX467uzu9e/fmwIEDji5JnJTCmoiIiIPUrl2b5cuXU7p0aXr16sWePXscXZI4IYU1ERERB6pZsybLli2jYsWK9OnTh507dzq6JHEyCmsiIiIOVq1aNZYsWUL16tXp27cv27Ztc3RJ4kQU1kRERJxAlSpVWLx4MXfeeSd9+/Zl48aNji5JnITCmoiIiJOoWLEi0dHRNG7cmICAANauXevoksQJKKyJiIg4kfLly7Nw4UJatWpF//79WblypaNLEgdTWBMREXEyZcuWZf78+XTs2JGBAweyZMkSR5ckDqSwJiIi4oTKlClDREQEPXr0YMiQISxcuNDRJYmDKKyJiIg4qdKlSzN79mwCAgIYOnQokZGRji5JHEBhTURExIn5+PgwY8YMhgwZwsiRI5k1a5ajS5IiprAmIiLi5Ly8vPj9998ZMWIEISEhhIeHO7okKUIKayIiIsWAp6cn06ZNY8yYMdx9991MnTrV0SVJEfFwdAEiIiKSPx4eHvz00094enpy3333kZmZyQMPPODosqSQKayJiIgUI+7u7vzwww94e3szbtw4MjIyeOSRRxxdlhQihTUREZFixs3NjW+//RYvLy8effRRMjIyeOKJJxxdlhQShTUREZFiyGQy8cUXX+Dl5cWTTz5Jeno6zz33nKPLkkKgsCYiIlJMmUwmPvnkE7y9vXn++efJyMjglVdecXRZUsAU1kRERIoxk8nEe++9h5eXF6+++ioZGRm88cYbmEwmR5cmBURhTUREpJgzmUy8+eab9sCWnp7OpEmTFNhchMKaiIiIi3jllVfw9vbmueeeIyMjg08++USBzQUorImIiLiQZ5991r7oICMjgy/+v737DbX6LuA4/rn33D+t2p1I2qTYzIkP1qBdzU1sUx8ke2BBNAzUkJwhK1ZR9CgYQsZ6MIophU8spw4ERxOiQdQK5jScTU2Zy7zTMZpJ7upVp+S9ejw9OHPm1LyI996v9/d6PTmX3+97fvd77n3y5vzO93xXrhRstzixBgCjzBNPPPHB13r09/dn9erVaW21adGtSqwBwCi0bNmytLe3Z+nSpRkYGMiaNWtSq9VGelrcALEGAKPUkiVL0tHRkcWLF2dgYCDr1q1LW1tbenp6sm3bNltV3SLEGgCMYosWLUpHR0cWLlyYc+fOZfny5ZkzZ056e3szc+bMTJkyZaSnyHW4gQ0Ao9z8+fPz/PPPZ/PmzZk2bVr6+vpSq9WycePGkZ4agyDWAKACuru709XVlf7+/tTr9dTr9WzYsCGNRmOkp8Z1iDUAGOVOnjyZWbNmpa+v77LjBw8ezO7du///kxsXhnBmDIbPrAHAKHfmzJnUarU0Go3UarXU6/UPzq1fvz5Tp069NPj4ruTQ2uToK8mpN5IL55LW9qTr3mT8w8mkJcnYqVf5LQyVlob3PwFg1Gs0Gtm7d29eeOGFbNq0Kfv370+SdHZ25uzZs8l7bybblybvbkla2pLG+SsvcvH4uFnJjF8lt08e5ldRTWINACqop6cnq1atyp49e7Jl/ePJ9seSRv3qkfZhLW1JSy2ZsTaZuGDoJ1txYg0AKuz0vl/n6SeX5tWDyY6DSd+ZZO2y5Buzrxz798PJ959Ltv4j6WhL5t2f/Hzl6oyb9viwz7tKLDAAgKo61ZPeP38rP97cDLHP3XXtoe8cS2atSN78d/LU15Ifzkte/Fsy99FvZ+DYG8M25SqywAAAqurVb2bCHfUc+WVy55jktUPJ9CevPvSp3yZn+pOdP0nu+kTz2AP3JHN/2sizK76SZc8cGLZpV4131gCgio7vTN7dks62eu4cc/3hv9mRfKn7UqglyRfvS6ZMSDa91NNcRcqQEGsAUEWHnm0uFBiEw8eTo6eSz3/mynMPTEp2v53m130wJMQaAFTR0VcGt/IzyZETzccJY648N2FMcvx00n94y82aGR8i1gCgik4NflHAfwaaj53tV577SMf7Y3otMhgqYg0AqqZxobkzwSDd9n6Q9V/lKWffD7nb2s7bmmqIiDUAqJqW1uYWUoN08fbnxduh/+vIiWTsx5POzvbmdbnp/FUBoIq67h300E+NTcZ1Ja+9deW5HYeS++9O0vXZmzc3LiPWAKCKxj886NWgSfLo9OR3u5N/Hrt07E+vJweOJPMfbE3GPzQEkySx3RQAVNPxXcnvpyVJfvGH5MSZ5F8nktUvJV+dnnTf3Rz2nUeSOz7ajLTuHyVjPpZ875Hk9Nnk6ReTT49N/roi6fzyzmTs1JF7PaOYWAOAqvrj7KT3L5n43fN5u/fqQ956Jpk4rvnzvneSHzyXbD2QdNSSed3Jz75eyyfv+UIy9+Vhm3bViDUAqKr33kxevC+50H/j12jtTOa9ntw++ebNi8v4zBoAVNXtk5MZa5O03OAFWprPF2pDykbuAFBlExckaSTbH0sa9cHtatDSlrTUmqE2ccGQT7Hq3AYFAJq3RLcvTd7d0oyxq0XbxePjZycPrvGO2jARawDAJcd3NTdlP7o1ObWvudNBa3vze9TGP5RMWmLV5zATawDAtTUu2JlghPnrAwDXJtRGnP8AAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDBxBoAQMHEGgBAwcQaAEDB/gtknnr7GfQ+/wAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def create_xyz_tree(\n", + " G, \n", + " length=1.0, \n", + " spread=np.pi/8,\n", + " spread_decay=0.9, \n", + " xy_only=False,\n", + " twist=0.0\n", + "):\n", + " root = next(n for n, d in G.in_degree() if d == 0)\n", + " pos = {root: (0.0, 0.0, 0.0)}\n", + "\n", + " def recurse(node, depth=1, theta=0.0, phi=np.pi/2):\n", + " children = [n for n in G.successors(node) if n not in pos]\n", + " if not children: return\n", + " n = len(children)\n", + " curr_spread = spread * (spread_decay ** (depth - 1))\n", + " x0, y0, z0 = pos[node]\n", + " phi = np.pi/2 if xy_only else phi\n", + " base_theta = theta + depth * twist\n", + " if n == 1:\n", + " thetas, phis = [base_theta], [phi]\n", + " else:\n", + " if xy_only:\n", + " thetas = np.linspace(base_theta - curr_spread/2, base_theta + curr_spread/2, n)\n", + " phis = [phi] * n\n", + " else:\n", + " thetas = np.linspace(base_theta, base_theta + 2 * np.pi, n, endpoint=False)\n", + " phis = [phi - curr_spread] * n\n", + " for th, ph, child in zip(thetas, phis, children):\n", + " x = x0 + length * np.sin(ph) * np.cos(th)\n", + " y = y0 + length * np.sin(ph) * np.sin(th)\n", + " z = z0 + length * np.cos(ph) * (not xy_only)\n", + " pos[child] = (x, y, z)\n", + " recurse(child, depth + 1, th, ph)\n", + "\n", + " recurse(root, theta=0.0, phi=np.pi/2)\n", + " for n, (x, y, z) in pos.items():\n", + " G.nodes[n].update({'x': float(x), 'y': float(y), 'z': float(z)})\n", + " return G\n", + "\n", + "# Create a simple tree\n", + "G = nx.DiGraph()\n", + "edges = [\n", + " (0, 1), (0, 2), (0, 3), # root 0 branches to 1, 2, 3\n", + " (1, 4), (1, 5), # node 1 branches to 4, 5\n", + " (2, 6), (2, 7), (2, 8), # node 2 branches to 6, 7, 8\n", + " (3, 9), # node 3 branches to 9\n", + " (4, 10), (4, 11), # node 4 branches to 10, 11\n", + " (7, 12), (7, 13), # node 7 branches to 12, 13\n", + " (9, 14), (9, 15), (9, 16) # node 9 branches to 14, 15, 16\n", + "]\n", + "G.add_edges_from(edges)\n", + "\n", + "G = create_xyz_tree(G, xy_only=True)\n", + "\n", + "# Create a 3D plot\n", + "fig = plt.figure(figsize=(10, 10))\n", + "ax = fig.add_subplot(111, projection='3d')\n", + "\n", + "# Get 3D positions\n", + "pos_3d = {n: (G.nodes[n]['x'], G.nodes[n]['y'], G.nodes[n]['z']) for n in G.nodes}\n", + "\n", + "# Plot nodes\n", + "for node, (x, y, z) in pos_3d.items():\n", + " ax.scatter(x, y, z, c='orange', s=200)\n", + " ax.text(x, y, z, str(node), ha='center', va='center')\n", + "\n", + "# Plot edges\n", + "for (u, v) in G.edges():\n", + " x1, y1, z1 = pos_3d[u]\n", + " x2, y2, z2 = pos_3d[v]\n", + " ax.plot([x1, x2], [y1, y2], [z1, z2], 'k-', alpha=0.5)\n", + "\n", + "ax.view_init(elev=0, azim=90) # Rotate the view: elevation=20 degrees, azimuth=45 degrees\n", + "plt.show()\n", + "\n", + "# Also show the 2D projection for reference\n", + "plt.figure(figsize=(6, 6))\n", + "pos_2d = {n: (G.nodes[n]['x'], G.nodes[n]['y']) for n in G.nodes}\n", + "nx.draw(G, pos_2d, with_labels=True, node_color='orange', node_size=200, arrows=True)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 86, "metadata": {}, "outputs": [], "source": [ @@ -432,7 +582,1064 @@ }, { "cell_type": "code", - "execution_count": 219, + "execution_count": 239, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "([1000.0,\n", + " 0,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 0,\n", + " 0.0,\n", + " 0.0,\n", + " 1.0,\n", + " 1.0,\n", + " 'apical',\n", + " 0.5,\n", + " 0.5,\n", + " 99.99,\n", + " 0.5,\n", + " 0.5,\n", + " Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", + " Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", + " 0.24,\n", + " -70.0,\n", + " -38.814059082992166,\n", + " -467.2217575574461,\n", + " 61.146926321832275,\n", + " 1000.0,\n", + " 0,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 1,\n", + " nan,\n", + " nan,\n", + " nan,\n", + " nan,\n", + " 'apical',\n", + " nan,\n", + " nan,\n", + " 0.0,\n", + " nan,\n", + " nan,\n", + " nan,\n", + " nan,\n", + " 0.4,\n", + " -70.0,\n", + " -35.24,\n", + " -400.77,\n", + " 11.68,\n", + " 1000.0,\n", + " 1,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 2,\n", + " 0.0,\n", + " 0.0,\n", + " 1.0,\n", + " 1.0,\n", + " 'apical',\n", + " 0.5,\n", + " 0.5,\n", + " 4.273938446576365,\n", + " 0.5,\n", + " 0.5,\n", + " Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", + " Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", + " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", + " 0.4,\n", + " -70.0,\n", + " -34.76658953359951,\n", + " -399.8027942229742,\n", + " 12.197484358005454,\n", + " 1000.0,\n", + " 1,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 3,\n", + " 'apical',\n", + " 0.0,\n", + " 0.4,\n", + " -70.0,\n", + " -33.9,\n", + " -397.85,\n", + " 12.15,\n", + " 1000.0,\n", + " 2,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 4,\n", + " 'apical',\n", + " 240.98216917972093,\n", + " 0.24,\n", + " -70.0,\n", + " -46.28514596269051,\n", + " -486.53457919707705,\n", + " 27.28,\n", + " 1000.0,\n", + " 3,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 5,\n", + " 'apical',\n", + " 46.75130571468936,\n", + " 0.4,\n", + " -70.0,\n", + " -28.605582752668862,\n", + " -387.37532948963417,\n", + " 25.76,\n", + " 1000.0,\n", + " 3,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 6,\n", + " 'apical',\n", + " 0.0,\n", + " 0.4,\n", + " -70.0,\n", + " -22.09,\n", + " -372.8,\n", + " 9.43,\n", + " 1000.0,\n", + " 4,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 7,\n", + " 'apical',\n", + " 86.53353014513984,\n", + " 0.24,\n", + " -70.0,\n", + " -60.46649412843316,\n", + " -414.1453724961543,\n", + " 11.51407401462471,\n", + " 1000.0,\n", + " 5,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 8,\n", + " 'apical',\n", + " 17.102847471669104,\n", + " 0.4,\n", + " -70.0,\n", + " -22.214137277739816,\n", + " -372.96551637031973,\n", + " 17.978920527015447,\n", + " 1000.0,\n", + " 5,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 9,\n", + " 'apical',\n", + " 0.0,\n", + " 0.4,\n", + " -70.0,\n", + " -19.99,\n", + " -367.96,\n", + " 15.84,\n", + " 1000.0,\n", + " 6,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 10,\n", + " 'apical',\n", + " 24.60469133685882,\n", + " 0.24,\n", + " -70.0,\n", + " -21.764906476169717,\n", + " -377.3156131006652,\n", + " 13.974884579197457,\n", + " 1000.0,\n", + " 6,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 11,\n", + " 'apical',\n", + " 0.0,\n", + " 0.24,\n", + " -70.0,\n", + " -19.63,\n", + " -387.74,\n", + " 15.52,\n", + " 1000.0,\n", + " 7,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 12,\n", + " 'apical',\n", + " 50.052056161692775,\n", + " 0.4,\n", + " -70.0,\n", + " -14.667438419442123,\n", + " -353.9810998217457,\n", + " 9.64331860144327,\n", + " 1000.0,\n", + " 7,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 13,\n", + " 'apical',\n", + " 0.0,\n", + " 0.55,\n", + " -70.0,\n", + " -12.52,\n", + " -343.56,\n", + " -2.16,\n", + " 1000.0,\n", + " 8,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 14,\n", + " 'apical',\n", + " 53.76132118557308,\n", + " 0.24,\n", + " -70.0,\n", + " -26.59348381607843,\n", + " -376.98191136107283,\n", + " -4.4,\n", + " 1000.0,\n", + " 9,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 15,\n", + " 'apical',\n", + " 159.71442568142288,\n", + " 0.5782846917122577,\n", + " -70.0,\n", + " -7.645618289361691,\n", + " -303.3455260496049,\n", + " 5.27622108401229,\n", + " 1000.0,\n", + " 9,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 16,\n", + " 'apical',\n", + " 0.0,\n", + " 0.71,\n", + " -70.0,\n", + " -4.13,\n", + " -268.18,\n", + " -5.589999999999999,\n", + " 1000.0,\n", + " 10,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 17,\n", + " 'apical',\n", + " 74.89970414900556,\n", + " 0.24,\n", + " -70.0,\n", + " -5.55926797785782,\n", + " -358.39305045595876,\n", + " -4.675272523401764,\n", + " 1000.0,\n", + " 10,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 18,\n", + " 'apical',\n", + " 0.0,\n", + " 0.24,\n", + " -70.0,\n", + " 12.91,\n", + " -382.04,\n", + " 5.110000000000001,\n", + " 1000.0,\n", + " 11,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 19,\n", + " 'apical',\n", + " 18.602360065325048,\n", + " 0.79,\n", + " -70.0,\n", + " -2.195,\n", + " -261.665,\n", + " 0.7599999999999998,\n", + " 1000.0,\n", + " 11,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 20,\n", + " 'apical',\n", + " 0.0,\n", + " 0.87,\n", + " -70.0,\n", + " -0.2599999999999998,\n", + " -255.15,\n", + " 7.109999999999999,\n", + " 1000.0,\n", + " 12,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 21,\n", + " 'apical',\n", + " 117.73329521015768,\n", + " 0.4,\n", + " -70.0,\n", + " -16.252533797319938,\n", + " -285.3936257314047,\n", + " 28.87,\n", + " 1000.0,\n", + " 13,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 22,\n", + " 'apical',\n", + " 3.485670667174398,\n", + " 0.87,\n", + " -70.0,\n", + " -0.044999999999999984,\n", + " -254.215,\n", + " 8.565,\n", + " 1000.0,\n", + " 13,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 23,\n", + " 'apical',\n", + " 0.0,\n", + " 0.87,\n", + " -70.0,\n", + " 0.17000000000000004,\n", + " -253.28,\n", + " 10.02,\n", + " 1000.0,\n", + " 14,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 24,\n", + " 'apical',\n", + " 69.90591435690905,\n", + " 0.24,\n", + " -70.0,\n", + " -8.907514028562915,\n", + " -266.4040510787294,\n", + " -11.251953956792763,\n", + " 1000.0,\n", + " 15,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 25,\n", + " 'apical',\n", + " 4.189092980586614,\n", + " 0.87,\n", + " -70.0,\n", + " 0.43499999999999994,\n", + " -252.16,\n", + " 11.77,\n", + " 1000.0,\n", + " 15,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 26,\n", + " 'apical',\n", + " 0.0,\n", + " 0.87,\n", + " -70.0,\n", + " 0.7,\n", + " -251.04,\n", + " 13.52,\n", + " 1000.0,\n", + " 16,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 27,\n", + " 'apical',\n", + " 113.68283329856779,\n", + " 0.24,\n", + " -70.0,\n", + " 7.776276453831945,\n", + " -281.71696585754637,\n", + " 34.33086009293123,\n", + " 1000.0,\n", + " 17,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 28,\n", + " 'apical',\n", + " 16.344032441943455,\n", + " 0.87,\n", + " -70.0,\n", + " -0.7360595221854835,\n", + " -244.8574840051365,\n", + " 8.372565868529955,\n", + " 1000.0,\n", + " 17,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 29,\n", + " 'apical',\n", + " 0.0,\n", + " 0.87,\n", + " -70.0,\n", + " -0.75,\n", + " -236.83,\n", + " 8.0,\n", + " 1000.0,\n", + " 18,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 30,\n", + " 'apical',\n", + " 83.6221267068054,\n", + " 0.24,\n", + " -70.0,\n", + " -16.58416113415944,\n", + " -260.2859901965372,\n", + " 43.27,\n", + " 1000.0,\n", + " 19,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 31,\n", + " 'apical',\n", + " 71.4833481477609,\n", + " 0.87,\n", + " -70.0,\n", + " 0.8145650574449815,\n", + " -214.8727592817948,\n", + " -2.2375183407402344,\n", + " 1000.0,\n", + " 19,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 32,\n", + " 'apical',\n", + " 0.0,\n", + " 1.03,\n", + " -70.0,\n", + " 6.38,\n", + " -184.71,\n", + " 0.9500000000000002,\n", + " 1000.0,\n", + " 20,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 33,\n", + " 'apical',\n", + " 56.00782300459446,\n", + " 0.4,\n", + " -70.0,\n", + " 21.32859606702451,\n", + " -232.50102170552017,\n", + " 15.070872611429797,\n", + " 1000.0,\n", + " 20,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 34,\n", + " 'apical',\n", + " 0.0,\n", + " 0.24,\n", + " -70.0,\n", + " 36.63,\n", + " -227.87,\n", + " 25.52,\n", + " 1000.0,\n", + " 21,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 35,\n", + " 'apical',\n", + " 8.651398442038415,\n", + " 1.1021193311462694,\n", + " -70.0,\n", + " 6.894451228843388,\n", + " -183.5945543449377,\n", + " 4.442708639932774,\n", + " 1000.0,\n", + " 21,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 36,\n", + " 'apical',\n", + " 0.0,\n", + " 1.18,\n", + " -70.0,\n", + " 7.45,\n", + " -182.39,\n", + " 8.56,\n", + " 1000.0,\n", + " 22,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 37,\n", + " 'apical',\n", + " 11.943457742966501,\n", + " 0.7297356833485694,\n", + " -70.0,\n", + " 4.052951545951412,\n", + " -184.0594273139219,\n", + " 6.411057259097895,\n", + " 1000.0,\n", + " 22,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 38,\n", + " 'apical',\n", + " 0.0,\n", + " 0.4,\n", + " -70.0,\n", + " 0.97,\n", + " -185.37,\n", + " 9.68,\n", + " 1000.0,\n", + " 23,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 39,\n", + " 'apical',\n", + " 11.834162412270667,\n", + " 1.18,\n", + " -70.0,\n", + " 7.385,\n", + " -181.41,\n", + " 14.395,\n", + " 1000.0,\n", + " 23,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 40,\n", + " 'apical',\n", + " 0.0,\n", + " 1.18,\n", + " -70.0,\n", + " 7.32,\n", + " -180.43,\n", + " 20.23,\n", + " 1000.0,\n", + " 24,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 41,\n", + " 'apical',\n", + " 60.482116932522686,\n", + " 0.4,\n", + " -70.0,\n", + " 16.78281904208192,\n", + " -194.19403766018746,\n", + " 29.763430972274353,\n", + " 1000.0,\n", + " 24,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 42,\n", + " 'apical',\n", + " 0.0,\n", + " 0.4,\n", + " -70.0,\n", + " 20.23,\n", + " -213.61,\n", + " 44.88,\n", + " 1000.0,\n", + " 25,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 43,\n", + " 'apical',\n", + " 2.2265219513851697,\n", + " 1.18,\n", + " -70.0,\n", + " 7.71,\n", + " -179.465,\n", + " 19.835,\n", + " 1000.0,\n", + " 25,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 44,\n", + " 'apical',\n", + " 0.0,\n", + " 1.18,\n", + " -70.0,\n", + " 8.1,\n", + " -178.5,\n", + " 19.44,\n", + " 1000.0,\n", + " 26,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 45,\n", + " 'apical',\n", + " 86.49836641101749,\n", + " 0.4,\n", + " -70.0,\n", + " 2.0134462481703657,\n", + " -192.55559886544083,\n", + " 30.605679248252855,\n", + " 1000.0,\n", + " 27,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 46,\n", + " 'apical',\n", + " 101.86565020617884,\n", + " 1.03,\n", + " -70.0,\n", + " 10.814626291741611,\n", + " -152.1248271646496,\n", + " 5.060345670700826,\n", + " 1000.0,\n", + " 27,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 47,\n", + " 'apical',\n", + " 0.0,\n", + " 1.34,\n", + " -70.0,\n", + " 12.31,\n", + " -122.33,\n", + " 5.84,\n", + " 1000.0,\n", + " 28,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 48,\n", + " 'apical',\n", + " 104.99517531503017,\n", + " 0.4,\n", + " -70.0,\n", + " 2.5229464777183814,\n", + " -159.7176697734082,\n", + " 35.99978727480884,\n", + " 1000.0,\n", + " 29,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 49,\n", + " 'soma',\n", + " 181.9201970835877,\n", + " 1.5,\n", + " -70.0,\n", + " 17.78697106422322,\n", + " -77.08047502970176,\n", + " 1.84,\n", + " 1000.0,\n", + " 29,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 50,\n", + " 'soma',\n", + " 0.0,\n", + " 2.6,\n", + " -70.0,\n", + " 4.06,\n", + " -11.45,\n", + " 0.0,\n", + " 1000.0,\n", + " 30,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 51,\n", + " 'apical',\n", + " 114.30351708313648,\n", + " 0.4688830535120067,\n", + " -70.0,\n", + " 25.35863421828102,\n", + " -135.4016477545103,\n", + " 44.08334802741253,\n", + " 1000.0,\n", + " 30,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 52,\n", + " 'apical',\n", + " 0.0,\n", + " 0.4,\n", + " -70.0,\n", + " 39.35,\n", + " -173.54,\n", + " 37.91,\n", + " 1000.0,\n", + " 31,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 53,\n", + " 'soma',\n", + " 12.483114327343436,\n", + " 6.360392267553557,\n", + " -70.0,\n", + " 1.9689989528610923,\n", + " -5.833291824125783,\n", + " 0.0,\n", + " 1000.0,\n", + " 31,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 54,\n", + " 'soma',\n", + " 0.0,\n", + " 8.119,\n", + " -70.0,\n", + " 0.0,\n", + " 0.0,\n", + " 0.0,\n", + " 1000.0,\n", + " 32,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 55,\n", + " 'soma',\n", + " 8.321000028787864,\n", + " 7.96,\n", + " -70.0,\n", + " -1.431913946300191,\n", + " 3.8861559375019596,\n", + " 0.0,\n", + " 1000.0,\n", + " 32,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 56,\n", + " 'soma',\n", + " 0.0,\n", + " 7.8,\n", + " -70.0,\n", + " -2.45,\n", + " 7.92,\n", + " 0.0,\n", + " 1000.0,\n", + " 33,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 57,\n", + " 'basal',\n", + " 58.4467372401343,\n", + " 0.71,\n", + " -70.0,\n", + " 10.779450509449843,\n", + " 7.087492384157699,\n", + " 17.28816403482587,\n", + " 1000.0,\n", + " 33,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 58,\n", + " 'basal',\n", + " 0.0,\n", + " 0.71,\n", + " -70.0,\n", + " 12.76,\n", + " 10.56,\n", + " 45.91,\n", + " 1000.0,\n", + " 34,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 59,\n", + " 'basal',\n", + " 60.35739302082753,\n", + " 1.1033645885509442,\n", + " -70.0,\n", + " -3.3812434965374667,\n", + " 8.86799569861848,\n", + " 30.105248620163,\n", + " 1000.0,\n", + " 34,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 60,\n", + " 'basal',\n", + " 0.0,\n", + " 0.71,\n", + " -70.0,\n", + " -12.15,\n", + " 12.01,\n", + " 54.88,\n", + " 1000.0,\n", + " 35,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 61,\n", + " 'basal',\n", + " 7.079516370872465,\n", + " 1.1854499190831111,\n", + " -70.0,\n", + " -11.078350976034892,\n", + " 12.047734120562152,\n", + " 58.25343037825636,\n", + " 1000.0,\n", + " 35,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 62,\n", + " 'basal',\n", + " 0.0,\n", + " 1.34,\n", + " -70.0,\n", + " -12.64,\n", + " 12.85,\n", + " 59.35,\n", + " 1000.0,\n", + " 36,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 63,\n", + " 'basal',\n", + " 7.970702603911401,\n", + " 0.79,\n", + " -70.0,\n", + " -13.57,\n", + " 13.225,\n", + " 51.36,\n", + " 1000.0,\n", + " 36,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 64,\n", + " 'basal',\n", + " 0.0,\n", + " 0.87,\n", + " -70.0,\n", + " -14.99,\n", + " 14.44,\n", + " 47.84,\n", + " 1000.0,\n", + " 37,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 65,\n", + " 'basal',\n", + " 65.42028120792062,\n", + " 0.55,\n", + " -70.0,\n", + " -21.744532926599987,\n", + " 12.614333841750017,\n", + " 48.43476897112083,\n", + " 1000.0,\n", + " 38,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 66,\n", + " 'basal',\n", + " 39.89804629510217,\n", + " 0.55,\n", + " -70.0,\n", + " -20.46462568500629,\n", + " 25.350645679037065,\n", + " 56.67776161924187,\n", + " 1000.0,\n", + " 38,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 67,\n", + " 'basal',\n", + " 0.0,\n", + " 0.55,\n", + " -70.0,\n", + " -24.81,\n", + " 41.27,\n", + " 53.2,\n", + " 1000.0,\n", + " 39,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 68,\n", + " 'basal',\n", + " 47.38843289953645,\n", + " 0.55,\n", + " -70.0,\n", + " -24.06011764647134,\n", + " 58.31648265295836,\n", + " 62.79,\n", + " 1000.0,\n", + " 40,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 69,\n", + " 'basal',\n", + " 11.12056895488611,\n", + " 0.55,\n", + " -70.0,\n", + " -27.373304357762073,\n", + " 45.933339226388014,\n", + " 53.240660871552414,\n", + " 1000.0,\n", + " 40,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 70,\n", + " 'basal',\n", + " 0.0,\n", + " 0.55,\n", + " -70.0,\n", + " -30.14,\n", + " 50.55,\n", + " 53.27,\n", + " 1000.0,\n", + " 41,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 71,\n", + " 'basal',\n", + " 15.819923328277275,\n", + " 0.55,\n", + " -70.0,\n", + " -31.761671906152685,\n", + " 51.63111460410179,\n", + " 60.936085374539985,\n", + " 1000.0,\n", + " 41,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 72,\n", + " 'basal',\n", + " 0.0,\n", + " 0.55,\n", + " -70.0,\n", + " -36.42,\n", + " 55.55,\n", + " 62.63,\n", + " 1000.0,\n", + " 42,\n", + " False,\n", + " 1.0,\n", + " 0,\n", + " 73,\n", + " 'basal',\n", + " 10.67453174716901,\n", + " 0.55,\n", + " -70.0,\n", + " -31.228660429037276,\n", + " 53.8782966236737,\n", + " 55.97186958848435,\n", + " 1000.0,\n", + " 42,\n", + " True,\n", + " 1.0,\n", + " 0,\n", + " 74,\n", + " 'basal',\n", + " 0.0,\n", + " ...],\n", + " PyTreeDef(CustomNode(MorphTree[()], [{0: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'e_test1': *, 'e_test2': *, 'gbar_test1': *, 'gbar_test2': *, 'groups': [*], 'h_test1': *, 'h_test2': *, 'length': *, 'm_test1': *, 'm_test2': *, 'nn_weights_test1': *, 'nn_weights_test2': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 1: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'e_test1': *, 'e_test2': *, 'gbar_test1': *, 'gbar_test2': *, 'groups': [*], 'h_test1': *, 'h_test2': *, 'length': *, 'm_test1': *, 'm_test2': *, 'nn_weights_test1': *, 'nn_weights_test2': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 2: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'e_test1': *, 'e_test2': *, 'gbar_test1': *, 'gbar_test2': *, 'groups': [*], 'h_test1': *, 'h_test2': *, 'length': *, 'm_test1': *, 'm_test2': *, 'nn_weights_test1': *, 'nn_weights_test2': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 3: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 4: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 5: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 6: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 7: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 8: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 9: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 10: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 11: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 12: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 13: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 14: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 15: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 16: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 17: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 18: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 19: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 20: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 21: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 22: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 23: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 24: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 25: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 26: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 27: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 28: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 29: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 30: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 31: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 32: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 33: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 34: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 35: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 36: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 37: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 38: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 39: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 40: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 41: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 42: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 43: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 44: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 45: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 46: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 47: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 48: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 49: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 50: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 51: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 52: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 53: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 54: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 55: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 56: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 57: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 58: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 59: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 60: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 61: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 62: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 63: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 64: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 65: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 66: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 67: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 68: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 69: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 70: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 71: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 72: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 73: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 74: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 75: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 76: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 77: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 78: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 79: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 80: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 81: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 82: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 83: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 84: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 85: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 86: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 87: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 88: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 89: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 90: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 91: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 92: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 93: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 94: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 95: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 96: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 97: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 98: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 99: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 100: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 101: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 102: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 103: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 104: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 105: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 106: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 107: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 108: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 109: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 110: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 111: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 112: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 113: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 114: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 115: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 116: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 117: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 118: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 119: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 120: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 121: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 122: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 123: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 124: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 125: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 126: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 127: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 128: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 129: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 130: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 131: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 132: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 133: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 134: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 135: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 136: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 137: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 138: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 139: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 140: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 141: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 142: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 143: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 144: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 145: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 146: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 147: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 148: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 149: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 150: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 151: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 152: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 153: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 154: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 155: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 156: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 157: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 158: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 159: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 160: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 161: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 162: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 163: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 164: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 165: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 166: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 167: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 168: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 169: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 170: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 171: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 172: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 173: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 174: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 175: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 176: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 177: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 178: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 179: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 180: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 181: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 182: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 183: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 184: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 185: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 186: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 187: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 188: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 189: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 190: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 191: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 192: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 193: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 194: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 195: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 196: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 197: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 198: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 199: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 200: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 201: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 202: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 203: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 204: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 205: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 206: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 207: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 208: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 209: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 210: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 211: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 212: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 213: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 214: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 215: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 216: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 217: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 218: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 219: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 220: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 221: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 222: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 223: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 224: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 225: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 226: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 227: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 228: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 229: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 230: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 231: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 232: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}}, {(0, 1): {'comp_edge': *, 'e_test2': *, 'gbar_test2': *, 'h_test2': *, 'm_test2': *, 'nn_weights_test2': *, 'synapse': *}, (0, 3): {'comp_edge': *, 'e_test1': *, 'gbar_test1': *, 'h_test1': *, 'm_test1': *, 'nn_weights_test1': *, 'synapse': *}, (1, 2): {'comp_edge': *, 'e_test1': *, 'e_test2': *, 'gbar_test1': *, 'gbar_test2': *, 'h_test1': *, 'h_test2': *, 'm_test1': *, 'm_test2': *, 'nn_weights_test1': *, 'nn_weights_test2': *, 'synapse': *}, (1, 4): {'comp_edge': *, 'synapse': *}, (2, 3): {'comp_edge': *, 'synapse': *}, (3, 5): {'comp_edge': *, 'synapse': *}, (3, 7): {'comp_edge': *, 'synapse': *}, (5, 6): {'comp_edge': *, 'synapse': *}, (6, 8): {'comp_edge': *, 'synapse': *}, (6, 10): {'comp_edge': *, 'synapse': *}, (8, 9): {'comp_edge': *, 'synapse': *}, (9, 12): {'comp_edge': *, 'synapse': *}, (9, 14): {'comp_edge': *, 'synapse': *}, (10, 11): {'comp_edge': *, 'synapse': *}, (11, 231): {'comp_edge': *, 'synapse': *}, (11, 232): {'comp_edge': *, 'synapse': *}, (12, 13): {'comp_edge': *, 'synapse': *}, (13, 15): {'comp_edge': *, 'synapse': *}, (13, 17): {'comp_edge': *, 'synapse': *}, (15, 16): {'comp_edge': *, 'synapse': *}, (16, 19): {'comp_edge': *, 'synapse': *}, (16, 21): {'comp_edge': *, 'synapse': *}, (17, 18): {'comp_edge': *, 'synapse': *}, (18, 226): {'comp_edge': *, 'synapse': *}, (18, 227): {'comp_edge': *, 'synapse': *}, (19, 20): {'comp_edge': *, 'synapse': *}, (20, 22): {'comp_edge': *, 'synapse': *}, (20, 24): {'comp_edge': *, 'synapse': *}, (22, 23): {'comp_edge': *, 'synapse': *}, (23, 25): {'comp_edge': *, 'synapse': *}, (23, 27): {'comp_edge': *, 'synapse': *}, (25, 26): {'comp_edge': *, 'synapse': *}, (26, 28): {'comp_edge': *, 'synapse': *}, (26, 30): {'comp_edge': *, 'synapse': *}, (28, 29): {'comp_edge': *, 'synapse': *}, (29, 31): {'comp_edge': *, 'synapse': *}, (29, 33): {'comp_edge': *, 'synapse': *}, (31, 32): {'comp_edge': *, 'synapse': *}, (32, 35): {'comp_edge': *, 'synapse': *}, (32, 37): {'comp_edge': *, 'synapse': *}, (33, 34): {'comp_edge': *, 'synapse': *}, (34, 224): {'comp_edge': *, 'synapse': *}, (34, 225): {'comp_edge': *, 'synapse': *}, (35, 36): {'comp_edge': *, 'synapse': *}, (36, 39): {'comp_edge': *, 'synapse': *}, (36, 41): {'comp_edge': *, 'synapse': *}, (37, 38): {'comp_edge': *, 'synapse': *}, (38, 216): {'comp_edge': *, 'synapse': *}, (38, 217): {'comp_edge': *, 'synapse': *}, (39, 40): {'comp_edge': *, 'synapse': *}, (40, 43): {'comp_edge': *, 'synapse': *}, (40, 45): {'comp_edge': *, 'synapse': *}, (41, 42): {'comp_edge': *, 'synapse': *}, (42, 208): {'comp_edge': *, 'synapse': *}, (42, 209): {'comp_edge': *, 'synapse': *}, (43, 44): {'comp_edge': *, 'synapse': *}, (44, 46): {'comp_edge': *, 'synapse': *}, (44, 48): {'comp_edge': *, 'synapse': *}, (46, 47): {'comp_edge': *, 'synapse': *}, (47, 49): {'comp_edge': *, 'synapse': *}, (47, 51): {'comp_edge': *, 'synapse': *}, (49, 50): {'comp_edge': *, 'synapse': *}, (50, 53): {'comp_edge': *, 'synapse': *}, (51, 52): {'comp_edge': *, 'synapse': *}, (52, 206): {'comp_edge': *, 'synapse': *}, (52, 207): {'comp_edge': *, 'synapse': *}, (53, 54): {'comp_edge': *, 'synapse': *}, (54, 55): {'comp_edge': *, 'synapse': *}, (54, 57): {'comp_edge': *, 'synapse': *}, (55, 56): {'comp_edge': *, 'synapse': *}, (56, 59): {'comp_edge': *, 'synapse': *}, (57, 58): {'comp_edge': *, 'synapse': *}, (58, 105): {'comp_edge': *, 'synapse': *}, (58, 107): {'comp_edge': *, 'synapse': *}, (59, 60): {'comp_edge': *, 'synapse': *}, (60, 61): {'comp_edge': *, 'synapse': *}, (60, 63): {'comp_edge': *, 'synapse': *}, (61, 62): {'comp_edge': *, 'synapse': *}, (62, 65): {'comp_edge': *, 'synapse': *}, (62, 66): {'comp_edge': *, 'synapse': *}, (63, 64): {'comp_edge': *, 'synapse': *}, (64, 79): {'comp_edge': *, 'synapse': *}, (64, 81): {'comp_edge': *, 'synapse': *}, (66, 67): {'comp_edge': *, 'synapse': *}, (67, 68): {'comp_edge': *, 'synapse': *}, (67, 69): {'comp_edge': *, 'synapse': *}, (69, 70): {'comp_edge': *, 'synapse': *}, (70, 71): {'comp_edge': *, 'synapse': *}, (70, 73): {'comp_edge': *, 'synapse': *}, (71, 72): {'comp_edge': *, 'synapse': *}, (72, 75): {'comp_edge': *, 'synapse': *}, (72, 76): {'comp_edge': *, 'synapse': *}, (73, 74): {'comp_edge': *, 'synapse': *}, (74, 77): {'comp_edge': *, 'synapse': *}, (74, 78): {'comp_edge': *, 'synapse': *}, (79, 80): {'comp_edge': *, 'synapse': *}, (80, 83): {'comp_edge': *, 'synapse': *}, (80, 84): {'comp_edge': *, 'synapse': *}, (81, 82): {'comp_edge': *, 'synapse': *}, (82, 91): {'comp_edge': *, 'synapse': *}, (82, 93): {'comp_edge': *, 'synapse': *}, (84, 85): {'comp_edge': *, 'synapse': *}, (85, 86): {'comp_edge': *, 'synapse': *}, (85, 88): {'comp_edge': *, 'synapse': *}, (86, 87): {'comp_edge': *, 'synapse': *}, (87, 89): {'comp_edge': *, 'synapse': *}, (87, 90): {'comp_edge': *, 'synapse': *}, (91, 92): {'comp_edge': *, 'synapse': *}, (92, 95): {'comp_edge': *, 'synapse': *}, (92, 96): {'comp_edge': *, 'synapse': *}, (93, 94): {'comp_edge': *, 'synapse': *}, (94, 97): {'comp_edge': *, 'synapse': *}, (94, 99): {'comp_edge': *, 'synapse': *}, (97, 98): {'comp_edge': *, 'synapse': *}, (98, 100): {'comp_edge': *, 'synapse': *}, (98, 102): {'comp_edge': *, 'synapse': *}, (100, 101): {'comp_edge': *, 'synapse': *}, (101, 103): {'comp_edge': *, 'synapse': *}, (101, 104): {'comp_edge': *, 'synapse': *}, (105, 106): {'comp_edge': *, 'synapse': *}, (106, 109): {'comp_edge': *, 'synapse': *}, (106, 111): {'comp_edge': *, 'synapse': *}, (107, 108): {'comp_edge': *, 'synapse': *}, (108, 201): {'comp_edge': *, 'synapse': *}, (108, 202): {'comp_edge': *, 'synapse': *}, (109, 110): {'comp_edge': *, 'synapse': *}, (110, 112): {'comp_edge': *, 'synapse': *}, (110, 114): {'comp_edge': *, 'synapse': *}, (112, 113): {'comp_edge': *, 'synapse': *}, (113, 115): {'comp_edge': *, 'synapse': *}, (113, 117): {'comp_edge': *, 'synapse': *}, (115, 116): {'comp_edge': *, 'synapse': *}, (116, 119): {'comp_edge': *, 'synapse': *}, (116, 120): {'comp_edge': *, 'synapse': *}, (117, 118): {'comp_edge': *, 'synapse': *}, (118, 121): {'comp_edge': *, 'synapse': *}, (118, 123): {'comp_edge': *, 'synapse': *}, (121, 122): {'comp_edge': *, 'synapse': *}, (122, 125): {'comp_edge': *, 'synapse': *}, (122, 127): {'comp_edge': *, 'synapse': *}, (123, 124): {'comp_edge': *, 'synapse': *}, (124, 151): {'comp_edge': *, 'synapse': *}, (124, 153): {'comp_edge': *, 'synapse': *}, (125, 126): {'comp_edge': *, 'synapse': *}, (126, 129): {'comp_edge': *, 'synapse': *}, (126, 130): {'comp_edge': *, 'synapse': *}, (127, 128): {'comp_edge': *, 'synapse': *}, (128, 131): {'comp_edge': *, 'synapse': *}, (128, 133): {'comp_edge': *, 'synapse': *}, (131, 132): {'comp_edge': *, 'synapse': *}, (132, 135): {'comp_edge': *, 'synapse': *}, (132, 136): {'comp_edge': *, 'synapse': *}, (133, 134): {'comp_edge': *, 'synapse': *}, (134, 146): {'comp_edge': *, 'synapse': *}, (134, 147): {'comp_edge': *, 'synapse': *}, (136, 137): {'comp_edge': *, 'synapse': *}, (137, 138): {'comp_edge': *, 'synapse': *}, (137, 140): {'comp_edge': *, 'synapse': *}, (138, 139): {'comp_edge': *, 'synapse': *}, (139, 142): {'comp_edge': *, 'synapse': *}, (139, 143): {'comp_edge': *, 'synapse': *}, (140, 141): {'comp_edge': *, 'synapse': *}, (141, 144): {'comp_edge': *, 'synapse': *}, (141, 145): {'comp_edge': *, 'synapse': *}, (147, 148): {'comp_edge': *, 'synapse': *}, (148, 149): {'comp_edge': *, 'synapse': *}, (148, 150): {'comp_edge': *, 'synapse': *}, (151, 152): {'comp_edge': *, 'synapse': *}, (152, 155): {'comp_edge': *, 'synapse': *}, (152, 157): {'comp_edge': *, 'synapse': *}, (153, 154): {'comp_edge': *, 'synapse': *}, (154, 193): {'comp_edge': *, 'synapse': *}, (154, 194): {'comp_edge': *, 'synapse': *}, (155, 156): {'comp_edge': *, 'synapse': *}, (156, 159): {'comp_edge': *, 'synapse': *}, (156, 161): {'comp_edge': *, 'synapse': *}, (157, 158): {'comp_edge': *, 'synapse': *}, (158, 182): {'comp_edge': *, 'synapse': *}, (158, 183): {'comp_edge': *, 'synapse': *}, (159, 160): {'comp_edge': *, 'synapse': *}, (160, 163): {'comp_edge': *, 'synapse': *}, (160, 165): {'comp_edge': *, 'synapse': *}, (161, 162): {'comp_edge': *, 'synapse': *}, (162, 171): {'comp_edge': *, 'synapse': *}, (162, 172): {'comp_edge': *, 'synapse': *}, (163, 164): {'comp_edge': *, 'synapse': *}, (164, 167): {'comp_edge': *, 'synapse': *}, (164, 168): {'comp_edge': *, 'synapse': *}, (165, 166): {'comp_edge': *, 'synapse': *}, (166, 169): {'comp_edge': *, 'synapse': *}, (166, 170): {'comp_edge': *, 'synapse': *}, (172, 173): {'comp_edge': *, 'synapse': *}, (173, 174): {'comp_edge': *, 'synapse': *}, (173, 176): {'comp_edge': *, 'synapse': *}, (174, 175): {'comp_edge': *, 'synapse': *}, (175, 177): {'comp_edge': *, 'synapse': *}, (175, 178): {'comp_edge': *, 'synapse': *}, (178, 179): {'comp_edge': *, 'synapse': *}, (179, 180): {'comp_edge': *, 'synapse': *}, (179, 181): {'comp_edge': *, 'synapse': *}, (183, 184): {'comp_edge': *, 'synapse': *}, (184, 185): {'comp_edge': *, 'synapse': *}, (184, 187): {'comp_edge': *, 'synapse': *}, (185, 186): {'comp_edge': *, 'synapse': *}, (186, 189): {'comp_edge': *, 'synapse': *}, (186, 190): {'comp_edge': *, 'synapse': *}, (187, 188): {'comp_edge': *, 'synapse': *}, (188, 191): {'comp_edge': *, 'synapse': *}, (188, 192): {'comp_edge': *, 'synapse': *}, (194, 195): {'comp_edge': *, 'synapse': *}, (195, 196): {'comp_edge': *, 'synapse': *}, (195, 197): {'comp_edge': *, 'synapse': *}, (197, 198): {'comp_edge': *, 'synapse': *}, (198, 199): {'comp_edge': *, 'synapse': *}, (198, 200): {'comp_edge': *, 'synapse': *}, (202, 203): {'comp_edge': *, 'synapse': *}, (203, 204): {'comp_edge': *, 'synapse': *}, (203, 205): {'comp_edge': *, 'synapse': *}, (209, 210): {'comp_edge': *, 'synapse': *}, (210, 211): {'comp_edge': *, 'synapse': *}, (210, 212): {'comp_edge': *, 'synapse': *}, (212, 213): {'comp_edge': *, 'synapse': *}, (213, 214): {'comp_edge': *, 'synapse': *}, (213, 215): {'comp_edge': *, 'synapse': *}, (217, 218): {'comp_edge': *, 'synapse': *}, (218, 219): {'comp_edge': *, 'synapse': *}, (218, 220): {'comp_edge': *, 'synapse': *}, (220, 221): {'comp_edge': *, 'synapse': *}, (221, 222): {'comp_edge': *, 'synapse': *}, (221, 223): {'comp_edge': *, 'synapse': *}, (227, 228): {'comp_edge': *, 'synapse': *}, (228, 229): {'comp_edge': *, 'synapse': *}, (228, 230): {'comp_edge': *, 'synapse': *}}, {'channels': {'test1': *, 'test2': *}, 'synapses': {'test1': *, 'test2': *}, 'xyzr': None}])))" + ] + }, + "execution_count": 239, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "jax.tree.flatten(morph_comps)" + ] + }, + { + "cell_type": "code", + "execution_count": 356, "metadata": {}, "outputs": [], "source": [ @@ -452,15 +1659,16 @@ "]\n", "\n", "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[-3])\n", + "# jx_comps = build_compartment_graph(jx_graph.copy(), ncomp=1)\n", "\n", - "morph_comps = compartmentalize(MorphTree.from_nx(jx_graph.copy()), num_comps=1)\n", - "morph_comps = _add_meta_data(morph_comps)\n", - "# jx_comps = build_compartment_graph(jx_graph, ncomp=1)" + "morph_tree = swc_to_morph_tree(\"../jaxley/tests/swc_files/\"+testcases[-3])\n", + "morph_comps = compartmentalize(morph_tree, num_comps=1)\n", + "morph_comps = _add_meta_data(morph_comps)" ] }, { "cell_type": "code", - "execution_count": 220, + "execution_count": 222, "metadata": {}, "outputs": [], "source": [ @@ -475,846 +1683,47 @@ "\n", "subtree = tree_view(morph_comps, list(range(0,2)))\n", "subtree = tree_set(subtree, \"length\", 99.99) # <-- setting on views works\n", - "# morph_comps = merge_trees([morph_comps, subtree])" + "morph_comps = merge_trees([morph_comps, subtree])" ] }, { "cell_type": "code", - "execution_count": 217, + "execution_count": 244, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{0: {'branch': 0,\n", - " 'branchpoint': False,\n", - " 'groups': ['apical'],\n", - " 'length': 244.22704536220328,\n", - " 'x': -38.814059082992166,\n", - " 'y': -467.2217575574461,\n", - " 'z': 61.146926321832275,\n", - " 'radius': 0.24,\n", - " 'cell': 0,\n", - " 'comp': 0,\n", - " 'capacitance': 1.0,\n", - " 'v': -70.0,\n", - " 'axial_resistivity': 1000.0,\n", - " 'gbar_test1': 1.0,\n", - " 'e_test1': 0.0,\n", - " 'nn_weights_test1': Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", - " 'm_test1': 0.5,\n", - " 'h_test1': 0.5,\n", - " 'gbar_test2': 1.0,\n", - " 'e_test2': 0.0,\n", - " 'nn_weights_test2': Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", - " 'm_test2': 0.5,\n", - " 'h_test2': 0.5},\n", - " 1: {'branch': 0,\n", - " 'branchpoint': True,\n", - " 'groups': ['apical'],\n", - " 'length': 0.0,\n", - " 'x': -35.24,\n", - " 'y': -400.77,\n", - " 'z': 11.68,\n", - " 'radius': 0.4,\n", - " 'cell': 0,\n", - " 'comp': 1,\n", - " 'capacitance': 1.0,\n", - " 'v': -70.0,\n", - " 'axial_resistivity': 1000.0}}" + "0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", + "1 NaN\n", + "2 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", + "3 NaN\n", + "4 NaN\n", + " ... \n", + "228 NaN\n", + "229 NaN\n", + "230 NaN\n", + "231 NaN\n", + "232 NaN\n", + "Name: nn_weights_test1, Length: 233, dtype: object" ] }, - "execution_count": 217, + "execution_count": 244, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "subtree.node_attrs" + "morph_comps.to_pandas()[0][\"nn_weights_test1\"]" ] }, { "cell_type": "code", - "execution_count": 201, + "execution_count": 260, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
branchbranchpointgroupslengthxyzradiuscellcomp...gbar_test1e_test1nn_weights_test1m_test1h_test1gbar_test2e_test2nn_weights_test2m_test2h_test2
00False[apical]244.227045-38.814059-467.22175861.1469260.2400...1.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.51.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.5
10True[apical]0.000000-35.240000-400.77000011.6800000.4001...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
21False[apical]4.273938-34.766590-399.80279412.1974840.4002...1.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.51.00.0[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...0.50.5
31True[apical]0.000000-33.900000-397.85000012.1500000.4003...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
42False[apical]240.982169-46.285146-486.53457927.2800000.2404...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
..................................................................
228150True[apical]0.000000-16.260000-519.90000051.2700000.240228...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
229151False[apical]91.768980-24.954915-530.30717926.3779280.240229...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
230152False[apical]7.767618-12.678710-521.40277651.2700000.240230...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
231153False[apical]127.91475612.046325-433.8306440.1500000.240231...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
232154False[apical]122.357698-7.370122-437.11824834.4700000.400232...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
\n", - "

233 rows × 23 columns

\n", - "
" - ], - "text/plain": [ - " branch branchpoint groups length x y \\\n", - "0 0 False [apical] 244.227045 -38.814059 -467.221758 \n", - "1 0 True [apical] 0.000000 -35.240000 -400.770000 \n", - "2 1 False [apical] 4.273938 -34.766590 -399.802794 \n", - "3 1 True [apical] 0.000000 -33.900000 -397.850000 \n", - "4 2 False [apical] 240.982169 -46.285146 -486.534579 \n", - ".. ... ... ... ... ... ... \n", - "228 150 True [apical] 0.000000 -16.260000 -519.900000 \n", - "229 151 False [apical] 91.768980 -24.954915 -530.307179 \n", - "230 152 False [apical] 7.767618 -12.678710 -521.402776 \n", - "231 153 False [apical] 127.914756 12.046325 -433.830644 \n", - "232 154 False [apical] 122.357698 -7.370122 -437.118248 \n", - "\n", - " z radius cell comp ... gbar_test1 e_test1 \\\n", - "0 61.146926 0.24 0 0 ... 1.0 0.0 \n", - "1 11.680000 0.40 0 1 ... NaN NaN \n", - "2 12.197484 0.40 0 2 ... 1.0 0.0 \n", - "3 12.150000 0.40 0 3 ... NaN NaN \n", - "4 27.280000 0.24 0 4 ... NaN NaN \n", - ".. ... ... ... ... ... ... ... \n", - "228 51.270000 0.24 0 228 ... NaN NaN \n", - "229 26.377928 0.24 0 229 ... NaN NaN \n", - "230 51.270000 0.24 0 230 ... NaN NaN \n", - "231 0.150000 0.24 0 231 ... NaN NaN \n", - "232 34.470000 0.40 0 232 ... NaN NaN \n", - "\n", - " nn_weights_test1 m_test1 h_test1 \\\n", - "0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", - "1 NaN NaN NaN \n", - "2 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... 0.5 0.5 \n", - "3 NaN NaN NaN \n", - "4 NaN NaN NaN \n", - ".. ... ... ... \n", - "228 NaN NaN NaN \n", - "229 NaN NaN NaN \n", - "230 NaN NaN NaN \n", - "231 NaN NaN NaN \n", - "232 NaN NaN NaN \n", - "\n", - " gbar_test2 e_test2 nn_weights_test2 \\\n", - "0 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", - "1 NaN NaN NaN \n", - "2 1.0 0.0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n", - "3 NaN NaN NaN \n", - "4 NaN NaN NaN \n", - ".. ... ... ... \n", - "228 NaN NaN NaN \n", - "229 NaN NaN NaN \n", - "230 NaN NaN NaN \n", - "231 NaN NaN NaN \n", - "232 NaN NaN NaN \n", - "\n", - " m_test2 h_test2 \n", - "0 0.5 0.5 \n", - "1 NaN NaN \n", - "2 0.5 0.5 \n", - "3 NaN NaN \n", - "4 NaN NaN \n", - ".. ... ... \n", - "228 NaN NaN \n", - "229 NaN NaN \n", - "230 NaN NaN \n", - "231 NaN NaN \n", - "232 NaN NaN \n", - "\n", - "[233 rows x 23 columns]" - ] - }, - "execution_count": 201, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "morph_comps.to_pandas()[0]" - ] - }, - { - "cell_type": "code", - "execution_count": 150, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "({'length': Array([2.44227045e+02, 4.27393845e+00, 2.40982169e+02, 4.67513057e+01,\n", - " 8.65335301e+01, 1.71028475e+01, 2.46046913e+01, 5.00520562e+01,\n", - " 5.37613212e+01, 1.59714426e+02, 7.48997041e+01, 1.86023601e+01,\n", - " 1.17733295e+02, 3.48567067e+00, 6.99059144e+01, 4.18909298e+00,\n", - " 1.13682833e+02, 1.63440324e+01, 8.36221267e+01, 7.14833481e+01,\n", - " 5.60078230e+01, 8.65139844e+00, 1.19434577e+01, 1.18341624e+01,\n", - " 6.04821169e+01, 2.22652195e+00, 8.64983664e+01, 1.01865650e+02,\n", - " 1.04995175e+02, 1.81920197e+02, 1.14303517e+02, 1.24831143e+01,\n", - " 8.32100003e+00, 5.84467372e+01, 6.03573930e+01, 7.07951637e+00,\n", - " 7.97070260e+00, 6.54202812e+01, 3.98980463e+01, 4.73884329e+01,\n", - " 1.11205690e+01, 1.58199233e+01, 1.06745317e+01, 1.93803826e+02,\n", - " 4.68279814e+01, 1.16410913e+02, 2.18482129e+01, 3.98674512e+01,\n", - " 1.31019920e+01, 1.14727338e+02, 2.62038740e+01, 2.36348559e+01,\n", - " 1.46372243e+02, 1.77078541e+02, 1.51908215e+02, 1.88632174e+01,\n", - " 1.99484663e+01, 2.01271439e+02, 9.98779052e+01, 7.20884214e+01,\n", - " 1.03907121e+02, 3.36359252e+01, 5.89085479e+01, 1.07287479e+02,\n", - " 7.34204122e+01, 2.08664292e+01, 6.14484518e+01, 7.76717167e+00,\n", - " 3.75958736e+01, 5.98194156e+00, 8.28050749e+01, 5.15007803e+01,\n", - " 7.69670339e+01, 1.38513551e+02, 5.89333860e-01, 7.13845088e+01,\n", - " 2.47290064e+02, 1.03945877e+01, 1.37263347e+02, 2.07062881e+02,\n", - " 8.30791299e+01, 1.37880444e+01, 2.48048336e+01, 2.33607253e+01,\n", - " 1.74379156e+01, 5.70210922e+01, 5.34781853e+01, 7.01609823e+01,\n", - " 1.41706274e+02, 1.99370310e+02, 2.27512040e+02, 1.94238703e+02,\n", - " 5.71602082e+01, 2.87768195e+01, 9.24722613e+01, 2.51768663e+00,\n", - " 8.65304227e+01, 1.82482876e-01, 3.18533866e+01, 6.42759470e+01,\n", - " 1.39461130e+01, 4.02934985e+01, 7.98859607e+01, 1.59913083e+02,\n", - " 2.82131445e+01, 1.00706363e+02, 4.29941742e+01, 2.31970368e+02,\n", - " 5.13527546e+01, 1.50636642e+01, 6.75241154e+01, 6.61563113e+01,\n", - " 1.26906107e+01, 1.76133011e+02, 4.50523713e+01, 2.06259293e+02,\n", - " 1.87169885e+01, 1.47306550e+01, 3.54588338e+01, 1.75242344e+02,\n", - " 1.32771667e+00, 1.29183383e+02, 5.74656307e-01, 1.40209297e+02,\n", - " 1.78636825e+01, 7.75760254e+01, 5.89367355e+01, 1.18174494e+02,\n", - " 7.61007831e+01, 6.06704256e+01, 9.94571441e+01, 9.31158162e+01,\n", - " 1.92990563e+02, 8.83708697e+01, 1.56182708e+02, 2.01756276e+01,\n", - " 4.55395873e+01, 3.14180157e+02, 4.96918789e+01, 1.46905134e+02,\n", - " 1.03873063e+02, 1.42322205e+02, 3.09882545e+01, 3.72726316e+01,\n", - " 6.08114959e+01, 2.70516732e+01, 6.01662185e+01, 8.38092975e+01,\n", - " 4.53456511e+01, 2.19301346e+02, 2.05210304e+02, 9.17689802e+01,\n", - " 7.76761757e+00, 1.27914756e+02, 1.22357698e+02], dtype=float64),\n", - " 'x': Array([-3.88140591e+01, -3.47665895e+01, -4.62851460e+01, -2.86055828e+01,\n", - " -6.04664941e+01, -2.22141373e+01, -2.17649065e+01, -1.46674384e+01,\n", - " -2.65934838e+01, -7.64561829e+00, -5.55926798e+00, -2.19500000e+00,\n", - " -1.62525338e+01, -4.50000000e-02, -8.90751403e+00, 4.35000000e-01,\n", - " 7.77627645e+00, -7.36059522e-01, -1.65841611e+01, 8.14565057e-01,\n", - " 2.13285961e+01, 6.89445123e+00, 4.05295155e+00, 7.38500000e+00,\n", - " 1.67828190e+01, 7.71000000e+00, 2.01344625e+00, 1.08146263e+01,\n", - " 2.52294648e+00, 1.77869711e+01, 2.53586342e+01, 1.96899895e+00,\n", - " -1.43191395e+00, 1.07794505e+01, -3.38124350e+00, -1.10783510e+01,\n", - " -1.35700000e+01, -2.17445329e+01, -2.04646257e+01, -2.40601176e+01,\n", - " -2.73733044e+01, -3.17616719e+01, -3.12286604e+01, -3.46899208e+01,\n", - " -4.09685246e+01, -4.65120057e+01, -3.84031315e+01, -1.34834327e+01,\n", - " -1.73996943e+01, -2.91027177e+01, -1.28358122e+01, -1.45804066e+01,\n", - " -1.11253485e+01, -8.15036285e+00, -2.21252519e+01, -2.70002952e+01,\n", - " -2.46579547e+01, -6.35780453e+01, -4.48365602e+01, -3.92184464e+01,\n", - " -7.13437925e+01, -5.51445682e+01, -6.44816671e+01, -9.35387104e+01,\n", - " -6.91735810e+01, 1.03711686e+01, 1.74618476e+01, 5.43191123e+00,\n", - " 1.19414126e+01, 2.84773808e+00, 1.93901408e+00, 1.93595787e-01,\n", - " 1.29500000e+00, -2.72412240e+01, -5.80263563e+00, 1.46500000e+00,\n", - " 2.22187553e+01, 2.53570369e+00, -1.84266862e+00, 1.51830631e+01,\n", - " 2.20613544e+01, -3.84324259e+00, 1.71926423e+00, -5.57872256e-01,\n", - " -7.05500000e+00, -1.55119060e+01, -4.13728233e+00, -3.67836032e+01,\n", - " -6.20384343e+01, 1.05045409e+01, -2.26490914e+01, 1.32178956e+01,\n", - " 7.66484909e+00, 2.31079088e+01, 1.61021887e+01, 1.46392832e+01,\n", - " 1.10439022e+01, 1.58050000e+01, 1.78764087e+01, 2.12141509e+01,\n", - " 1.89122741e+01, 2.25274810e+01, 3.25100849e+01, 2.20398342e+01,\n", - " 1.89171231e+01, 5.45815165e+01, 5.40631551e+01, 8.34180477e+01,\n", - " 2.02817763e+01, 1.98801349e+01, 1.25974545e+01, 2.77192419e+01,\n", - " 2.20200000e+01, 2.96250976e+01, 3.23790033e+01, 5.64145841e+01,\n", - " 2.72277182e+01, 2.94151398e+01, 2.78960365e+01, 6.50720438e+01,\n", - " 3.15165333e+01, 5.63451453e+01, 3.10089173e+01, 1.77797413e+01,\n", - " 1.11620758e+01, 9.16106710e+00, 9.64909680e+00, 1.29319048e+01,\n", - " -5.55020829e+00, 2.96935061e+01, 2.25534511e+01, 5.56528605e+01,\n", - " 9.99225200e+01, 6.09454728e+01, 2.10102712e+01, 2.17317292e+01,\n", - " 2.82162141e+01, 7.31353939e+01, 4.62060688e+01, 9.44369001e+01,\n", - " 9.65242301e+01, -1.17380615e+01, -9.09180601e+00, -4.08751305e+00,\n", - " -1.72995328e+01, -3.10644853e+01, -4.28129473e+01, 6.47747363e+01,\n", - " 4.36760765e+01, 4.51429852e+01, 2.91750433e+01, -2.49549155e+01,\n", - " -1.26787102e+01, 1.20463251e+01, -7.37012198e+00], dtype=float64),\n", - " 'y': Array([-467.22175756, -399.80279422, -486.5345792 , -387.37532949,\n", - " -414.1453725 , -372.96551637, -377.3156131 , -353.98109982,\n", - " -376.98191136, -303.34552605, -358.39305046, -261.665 ,\n", - " -285.39362573, -254.215 , -266.40405108, -252.16 ,\n", - " -281.71696586, -244.85748401, -260.2859902 , -214.87275928,\n", - " -232.50102171, -183.59455434, -184.05942731, -181.41 ,\n", - " -194.19403766, -179.465 , -192.55559887, -152.12482716,\n", - " -159.71766977, -77.08047503, -135.40164775, -5.83329182,\n", - " 3.88615594, 7.08749238, 8.8679957 , 12.04773412,\n", - " 13.225 , 12.61433384, 25.35064568, 58.31648265,\n", - " 45.93333923, 51.6311146 , 53.87829662, 72.59061764,\n", - " 67.5258203 , 90.24287678, 62.48958086, 17.41335817,\n", - " 16.59322005, 30.47593334, 18.89287553, 25.87304953,\n", - " 34.73637081, 46.83288325, 71.8043282 , 27.79545894,\n", - " 19.7320453 , 106.42462676, 63.67345983, 28.461845 ,\n", - " 13.60008591, 60.41825342, 51.51458261, 103.55194279,\n", - " 97.88617877, 11.693338 , 5.92279773, 11.2442272 ,\n", - " 13.02718082, 13.8047606 , 36.66509591, 21.27139234,\n", - " 13.865 , 82.42212564, 37.49542511, 13.58 ,\n", - " 16.19182246, 13.55030688, 14.24151464, 65.01517003,\n", - " 28.39995684, 24.25018969, 30.79639145, 14.44969604,\n", - " 21.1 , 25.70793736, 38.95245081, 43.61421049,\n", - " 56.63902138, 104.13980011, 128.72752265, 61.24197344,\n", - " 56.74388898, 80.96430726, 100.16385372, 17.57025633,\n", - " 37.5829197 , 17.47 , 19.03547843, 22.4971067 ,\n", - " 17.6838308 , 38.1357177 , 43.22117954, 65.74640932,\n", - " 47.65934149, 71.65161919, 50.48598164, 56.32578249,\n", - " 34.38530483, 54.39253945, 76.57172314, 68.73963285,\n", - " 61.15 , 129.01740518, 80.26277401, 76.98769888,\n", - " 31.4711477 , 44.24275793, 51.97663607, 114.39658219,\n", - " 51.13726417, 121.04355091, 66.35524526, 114.98295441,\n", - " 80.27069362, 108.96831315, 96.68302983, 151.95575124,\n", - " 127.09725403, -2.67126416, 9.57396065, 1.81999783,\n", - " 41.86340217, -208.54174156, -130.79601473, -223.35724107,\n", - " -219.61857652, -327.27298222, -235.51987584, -285.77979536,\n", - " -265.36770569, -209.22123097, -188.67837147, -186.40151314,\n", - " -208.19400105, -238.99450251, -223.94711117, -218.78824582,\n", - " -216.75015638, -461.63075952, -467.24896436, -530.30717898,\n", - " -521.40277554, -433.83064446, -437.11824757], dtype=float64),\n", - " 'z': Array([ 61.14692632, 12.19748436, 27.28 , 25.76 ,\n", - " 11.51407401, 17.97892053, 13.97488458, 9.6433186 ,\n", - " -4.4 , 5.27622108, -4.67527252, 0.76 ,\n", - " 28.87 , 8.565 , -11.25195396, 11.77 ,\n", - " 34.33086009, 8.37256587, 43.27 , -2.23751834,\n", - " 15.07087261, 4.44270864, 6.41105726, 14.395 ,\n", - " 29.76343097, 19.835 , 30.60567925, 5.06034567,\n", - " 35.99978727, 1.84 , 44.08334803, 0. ,\n", - " 0. , 17.28816403, 30.10524862, 58.25343038,\n", - " 51.36 , 48.43476897, 56.67776162, 62.79 ,\n", - " 53.24066087, 60.93608537, 55.97186959, 35.18036425,\n", - " 58.73176729, 53.04 , 57.68 , 41.53315306,\n", - " 53.36 , 26.39211569, 34.5980048 , 31.59748853,\n", - " 25.0789444 , -32.10959913, 17.94486003, 53.10575416,\n", - " 49.45136379, 50.12462076, 31.64510844, 39.82193807,\n", - " 41.37762411, 47.0270826 , 61.04 , 38.71177192,\n", - " 43.42675924, 46.82048985, 37.3824518 , 37.78761858,\n", - " 20.64790945, 42.47678577, 31.10010505, 24.42659665,\n", - " 6.635 , 38.91897803, 12.56 , 3.84 ,\n", - " 19.38012979, 44.71551285, -28.97702095, 53.88555438,\n", - " 46.94412938, 30.79487086, 17.68 , 21.03781985,\n", - " 33.54 , 23.16780124, 23.12 , 14.8 ,\n", - " 22.79895063, 17.89706698, 54.31 , -22.33046626,\n", - " 24.56167616, 8.23 , 5.59 , 26.23 ,\n", - " 30.63 , 26.23 , 41.29887915, 17.00837525,\n", - " 31.40269374, 13.69093954, 29.31746084, 19.04132129,\n", - " 24.5473551 , 25.04 , 15.84 , 10.179687 ,\n", - " 21.76 , 15.44924698, 10.58139591, 18.15 ,\n", - " 15.68 , 5.72997792, 0.91787377, 53.70443838,\n", - " 50.42479344, 54.85576002, 49.55335055, 59.06966685,\n", - " 56.33915476, 58.88 , 56.56 , 34.01003695,\n", - " 30.71 , 58.7655592 , 20.02441116, 15.76 ,\n", - " 16.30609289, 15.59233597, 40.87062569, 39.75 ,\n", - " 33.77031441, 38.62313788, 4.15 , 45.45387938,\n", - " 48.05727869, 39.06053515, 34.91626415, 22.92708681,\n", - " 40.99827221, 36.08 , 20.57528003, 40.79519918,\n", - " 45.52 , 42.24970713, 29.64160623, 36.28412232,\n", - " 37.63106542, 1.95884902, -2.28342966, 26.3779279 ,\n", - " 51.27 , 0.15 , 34.47 ], dtype=float64),\n", - " 'radius': Array([0.24 , 0.4 , 0.24 , 0.4 , 0.24 ,\n", - " 0.4 , 0.24 , 0.4 , 0.24 , 0.57828469,\n", - " 0.24 , 0.79 , 0.4 , 0.87 , 0.24 ,\n", - " 0.87 , 0.24 , 0.87 , 0.24 , 0.87 ,\n", - " 0.4 , 1.10211933, 0.72973568, 1.18 , 0.4 ,\n", - " 1.18 , 0.4 , 1.03 , 0.4 , 1.5 ,\n", - " 0.46888305, 6.36039227, 7.96 , 0.71 , 1.10336459,\n", - " 1.18544992, 0.79 , 0.55 , 0.55 , 0.55 ,\n", - " 0.55 , 0.55 , 0.55 , 0.24 , 0.55 ,\n", - " 0.24 , 0.55 , 0.87 , 0.55 , 0.4 ,\n", - " 0.67599993, 0.55 , 0.55 , 0.4 , 0.24 ,\n", - " 0.55 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", - " 0.4 , 0.4 , 0.4 , 0.4 , 0.24 ,\n", - " 0.55 , 0.4 , 0.55 , 0.55 , 0.55 ,\n", - " 0.55 , 0.55 , 0.475 , 0.4 , 0.55 ,\n", - " 0.87 , 0.4 , 1.34 , 0.43771301, 0.4 ,\n", - " 0.4 , 0.4 , 0.4 , 1.03 , 0.475 ,\n", - " 0.55 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", - " 0.4 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", - " 0.87 , 0.4 , 0.87 , 0.4 , 0.24 ,\n", - " 0.55 , 0.24 , 0.24 , 0.24 , 0.24 ,\n", - " 0.24 , 0.24 , 0.4 , 0.4 , 0.31876093,\n", - " 0.4 , 0.24 , 0.24 , 0.4 , 0.24 ,\n", - " 0.4 , 0.41539049, 0.42840312, 0.4 , 0.4 ,\n", - " 0.4 , 0.4 , 0.4 , 0.24 , 0.24 ,\n", - " 0.24 , 0.24 , 0.24 , 0.24 , 0.4 ,\n", - " 0.4 , 1.18 , 0.55 , 0.55 , 0.4 ,\n", - " 0.4 , 0.4 , 0.24 , 0.4 , 0.4 ,\n", - " 0.24 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", - " 0.4 , 0.24 , 0.24 , 0.24 , 0.24 ,\n", - " 0.24 , 0.24 , 0.24 , 0.24 , 0.4 ], dtype=float64),\n", - " 'cell': Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0], dtype=int64),\n", - " 'comp': Array([ 0, 2, 4, 5, 7, 8, 10, 12, 14, 15, 17, 19, 21,\n", - " 22, 24, 25, 27, 28, 30, 31, 33, 35, 37, 39, 41, 43,\n", - " 45, 46, 48, 49, 51, 53, 55, 57, 59, 61, 63, 65, 66,\n", - " 68, 69, 71, 73, 75, 76, 77, 78, 79, 81, 83, 84, 86,\n", - " 88, 89, 90, 91, 93, 95, 96, 97, 99, 100, 102, 103, 104,\n", - " 105, 107, 109, 111, 112, 114, 115, 117, 119, 120, 121, 123, 125,\n", - " 127, 129, 130, 131, 133, 135, 136, 138, 140, 142, 143, 144, 145,\n", - " 146, 147, 149, 150, 151, 153, 155, 157, 159, 161, 163, 165, 167,\n", - " 168, 169, 170, 171, 172, 174, 176, 177, 178, 180, 181, 182, 183,\n", - " 185, 187, 189, 190, 191, 192, 193, 194, 196, 197, 199, 200, 201,\n", - " 202, 204, 205, 206, 207, 208, 209, 211, 212, 214, 215, 216, 217,\n", - " 219, 220, 222, 223, 224, 225, 226, 227, 229, 230, 231, 232], dtype=int64),\n", - " 'capacitance': Array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1.], dtype=float64),\n", - " 'v': Array([-70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70.], dtype=float64),\n", - " 'axial_resistivity': Array([1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000.], dtype=float64),\n", - " 'gbar_test1': Array([1., 1.], dtype=float64),\n", - " 'e_test1': Array([0., 0.], dtype=float64),\n", - " 'nn_weights_test1': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]],\n", - " \n", - " [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", - " 'm_test1': Array([0.5, 0.5], dtype=float64),\n", - " 'h_test1': Array([0.5, 0.5], dtype=float64),\n", - " 'gbar_test2': Array([1., 1.], dtype=float64),\n", - " 'e_test2': Array([0., 0.], dtype=float64),\n", - " 'nn_weights_test2': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]],\n", - " \n", - " [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", - " 'm_test2': Array([0.5, 0.5], dtype=float64),\n", - " 'h_test2': Array([0.5, 0.5], dtype=float64)},\n", - " {'gbar_test2': Array([1., 1.], dtype=float64),\n", - " 'e_test2': Array([0., 0.], dtype=float64),\n", - " 'nn_weights_test2': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]],\n", - " \n", - " [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", - " 'm_test2': Array([0.5, 0.5], dtype=float64),\n", - " 'h_test2': Array([0.5, 0.5], dtype=float64),\n", - " 'gbar_test1': Array([1., 1.], dtype=float64),\n", - " 'e_test1': Array([0., 0.], dtype=float64),\n", - " 'nn_weights_test1': Array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]],\n", - " \n", - " [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]], dtype=float64),\n", - " 'm_test1': Array([0.5, 0.5], dtype=float64),\n", - " 'h_test1': Array([0.5, 0.5], dtype=float64)})" - ] - }, - "execution_count": 150, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "tree_to_pytree(morph_comps)" + "jax_nodes, jax_edges = tree_to_pytree(morph_comps)" ] }, { @@ -1465,402 +1874,6 @@ "# plt.tight_layout()\n", "# plt.show()" ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "def infer_module_type_from_inds(idxs: pd.DataFrame) -> str:\n", - " nuniques = idxs[[\"cell_index\", \"branch_index\", \"comp_index\"]].nunique()\n", - " nuniques.index = [\"cell\", \"branch\", \"compartment\"]\n", - " nuniques = pd.concat([pd.Series({\"network\": 1}), nuniques])\n", - " return_type = nuniques.loc[nuniques == 1].index[-1]\n", - " return return_type\n", - "\n", - "\n", - "def build_module_scaffold(\n", - " idxs: pd.DataFrame,\n", - " return_type: Optional[str] = None,\n", - " parent_branches: Optional[List[np.ndarray]] = None,\n", - ") -> Union[jx.Network, jx.Cell, jx.Branch, jx.Compartment]:\n", - " \"\"\"Builds a skeleton module from a DataFrame of indices.\n", - " This is useful for instantiating a module that can be filled with data later.\n", - " Args:\n", - " idxs: DataFrame containing cell_index, branch_index, comp_index, i.e.\n", - " Module.nodes or View.view.\n", - " return_type: Type of module to return. If None, the type is inferred from the\n", - " number of unique values in the indices. I.e. only 1 unique cell_index\n", - " and 1 unique branch_index -> return_type = \"jx.Branch\".\n", - " Returns:\n", - " A skeleton module with the correct number of compartments, branches, cells, or\n", - " networks.\"\"\"\n", - " return_types = [\"compartment\", \"branch\", \"cell\", \"network\"]\n", - " build_cache = {k: [] for k in return_types}\n", - "\n", - " if return_type is None: # infer return type from idxs\n", - " return_type = infer_module_type_from_inds(idxs)\n", - "\n", - " comp = jx.Compartment()\n", - " build_cache[\"compartment\"] = [comp]\n", - "\n", - " if return_type in return_types[1:]:\n", - " nsegs = idxs[\"branch_index\"].value_counts().iloc[0]\n", - " branch = jx.Branch([comp for _ in range(nsegs)])\n", - " build_cache[\"branch\"] = [branch]\n", - "\n", - " if return_type in return_types[2:]:\n", - " for cell_id, cell_groups in idxs.groupby(\"cell_index\"):\n", - " num_branches = cell_groups[\"branch_index\"].nunique()\n", - " default_parents = np.arange(num_branches) - 1 # ignores morphology\n", - " parents = (\n", - " default_parents if parent_branches is None else parent_branches[cell_id]\n", - " )\n", - " cell = jx.Cell([branch] * num_branches, parents)\n", - " build_cache[\"cell\"].append(cell)\n", - "\n", - " if return_type in return_types[3:]:\n", - " build_cache[\"network\"] = [jx.Network(build_cache[\"cell\"])]\n", - "\n", - " module = build_cache[return_type][0]\n", - " build_cache.clear()\n", - " return module" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "def convert_view_to_module(view: View, reset_index: bool = True) -> \"Module\":\n", - " \"\"\"Extract part of a module and return a copy of its View or a new module.\n", - "\n", - " This can be used to call `jx.integrate` on part of a Module.\n", - "\n", - " Args:\n", - " reset_index: if True, the indices of the new module are reset to start from 0.\n", - " as_module: if True, a new module is returned instead of a View.\n", - "\n", - " Returns:\n", - " A part of the module or a copied view of it.\"\"\"\n", - " view = deepcopy(view)\n", - " if reset_index:\n", - " view.nodes.reset_index(drop=True, inplace=True)\n", - " view.edges.reset_index(drop=True, inplace=True)\n", - " # TODO: also re-enumerate cell,branch,comp indices in nodes and edges\n", - "\n", - " testnodes = view.nodes.copy()\n", - " testnodes.rename({\"global_\"+k:k for k in [\"cell_index\", \"branch_index\", \"comp_index\"]}, axis=1, inplace=True)\n", - " mod_type = infer_module_type_from_inds(testnodes)\n", - " module = build_module_scaffold(testnodes, mod_type)\n", - " module.__dict__.update(view.__dict__)\n", - " return module" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Added 2 recordings. See `.recordings` for details.\n" - ] - }, - { - "data": { - "text/plain": [ - "Array([[-70. , -69.48756081, -69.09088174, -68.77443768,\n", - " -68.51477492, -68.29603413, -68.10727942, -67.94084395,\n", - " -67.79127429, -67.65464046, -67.52807603, -67.40946647,\n", - " -67.29723486, -67.19019277, -67.0874353 , -66.98826644,\n", - " -66.89214546, -66.7986481 , -66.70743824, -66.61824695,\n", - " -66.53085703, -66.44509138, -66.36080422, -66.27787448,\n", - " -66.19620072, -66.11569714, -66.03629063, -65.9579183 ,\n", - " -65.8805257 , -65.80406526, -65.72849517, -65.6537784 ,\n", - " -65.57988194, -65.50677619, -65.43443445, -65.3628325 ,\n", - " -65.29194826, -65.22176147, -65.15225352, -65.08340718,\n", - " -65.01520646]], dtype=float64)" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "branch = jx.Branch(ncomp=2)\n", - "branch[0].insert(HH())\n", - "branch.record()\n", - "\n", - "comp = branch[0]\n", - "comp = convert_view_to_module(comp)\n", - "jx.integrate(comp, t_max=1)" - ] - }, - { - "attachments": { - "image.png": { - "image/png": "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lx1wE8y78lR3dzduPuZf6C4xek2OsJeHcg6P4dvfHHlVl7qdFzZnqLijzr/32g1/1P10wutwV6VnaB++MeKN4R6Ls27bSfOvLUw/eZMmTQoODrZarQcOHPj663ObqK5atWr69OnLli1zOp0ZGRn1kqZL2bVrV8+ePceMGVNRUbFgwQL/qY6lpaVffPHF1KlT1Wr15s2bly9fTkQ//fSTUCi8//77n3jiCaPRmJ2dXVFR4bvl6NGjNTU1N9988549e/x7EQqFAwYMWLRoUcMB8PtF+rahbAtNPGNDZWVly5YtmzFjhkAgqKqq2rRp0/jx4/kqu93es2fP++67TyKRFBcXL1iwgD/uZvv27R07dkxLS/N6vSdPnty2bVszp7g2auHChY8//viwYcOsVuv69evrpZA7duy48847MzIyGt74888/p6amrl271r9w3rx5arWaiOLj4/v27ZuVlTVv3rwmet+5c2dgYOCECRMUCsWxY8c+/vhj/9rY2NiwsLDdu3c3vPG2227bvn17w0gaAAAAAAAAANoOExsbe73H0OYCbu+iHBhX9uaW6z2Q64ARCsLmDjes+c129NxRLaqh3RR9O/J561/Vyy+/XFZWxmeRrWXQoEHDhw+fPXu2f2FKSsrQoUPnzJnT8PqnnnoqLi7uhRde4BdiN9MXX3yRnp7uW4vdhLZ4xuuoX79+Tz/99NSpU+vtFUBEQqHw/fffX7FiRaOzIFvF008/bTAYVq9eXa88LCxswYIFzz77LPayBAAAAAAAALiWrs8syysVPWB81/vnNlr1y5yunMfdaBUJGaFSwohF8ltiHVexI+SfGufx6j/fL9LJr/dA/vR27dql1WpVKpX/IS0MwyxZsqTR6xMTE5cvX97MvFKpVIpEol69esnl8r/btolisTgwMHDUqFEZGRkN80oi8ng86enpQUFBbTQAgUBQVlb244+NhPg6nS49PR15JQAAAAAAAMA19ueILIv3ri7eW38C1GVJOgaFvngHeTjH6SrjpqNtMbA/BWdBtfPvFYK1CY7jvv/++3qF9Y639jdt2rTmN/7888/37NnTaDR+9tlnbbqWvB269957R48effz4cd9WAA3l5OTk5OS00QC8Xu/69esbrTp+/HgbdQoAAAAAAAAATfhbLAxvVzQP9Wm03PZb8WX3lAQAAAAAAAAAAPjLQ2QJAAAA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" - } - }, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- change param / state naming convenetion for channels and synapses\n", - "- ensure that channel/synapse currents are prefixed on the module side\n", - "- ensure that args and kwargs in channels functions are same order and standardized (enforce this with tests)\n", - "- make channel / synapse name user facing ?\n", - "- jx.integrate(net1, t_max=0) runs one step\n", - "- are we testing inner vs outer loop of setting states / params in init_states / _step_channel_currents etc?\n", - "- add test to see if indices are handled correctly for two different mechs changing the same state at non-overlapping indices\n", - "- fix: ![image.png](attachment:image.png)\n", - "- add prepare_mechansim function (assert name does not exist already, assert conform to build rules)\n", - "- warn if states / params does not contain all global params\n", - "update_states vs. init_state\n", - "try:\n", - " channel.update_states()\n", - " channel.compute_current()\n", - " channel.init_states()\n", - "except KeyError:\n", - " warn(\"Some global param / state seems to be misssing\")\n", - "\n", - "\n", - "- in the new channel API, `_filter_params_states` would have to filter potentially all channels, even the ones not in the channel. Better Solution! only filter global states!\n", - "- add current_name to synapses\n", - "- store global parameters in jaxnodes only once! i.e. for any global param jaxnodes[\"global_param_name\"].shape == (1,) and duplicate if it is used multiple times\n", - "- should compute_current get dt arg?" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "def get_params_all_trainable(net):\n", - " net.cell(\"all\").branch(\"all\").loc(\"all\").make_trainable(\"HH_gNa\")\n", - " params = net.get_parameters()\n", - " params[0][\"HH_gNa\"] = params[0][\"HH_gNa\"].at[:].set(0.0)\n", - " net.to_jax()\n", - " pstate = params_to_pstate(params, net.indices_set_by_trainables)\n", - " print(pstate)\n", - " return net.get_all_parameters(pstate, voltage_solver=\"jaxley.thomas\")\n", - "\n", - "def get_params_set(net):\n", - " net.set(\"HH_gNa\", 0.0)\n", - " params = net.get_parameters()\n", - " net.to_jax()\n", - " pstate = params_to_pstate(params, net.indices_set_by_trainables)\n", - " return net.get_all_parameters(pstate, voltage_solver=\"jaxley.thomas\")\n", - "\n", - "def SimpleComp():\n", - " comp = jx.Compartment()\n", - " return comp\n", - "\n", - "def SimpleBranch(ncomp):\n", - " comp = jx.Compartment()\n", - " branch = jx.Branch([comp]*ncomp)\n", - " return branch\n", - "\n", - "def SimpleCell(nbranch, ncomp):\n", - " branch = SimpleBranch(ncomp)\n", - " cell = jx.Cell([branch]*nbranch, parents=[-1, 0, 0, 1, 1, 2, 2, 3, 3][:nbranch])\n", - " return cell\n", - "\n", - "def SimpleNet(ncell, nbranch, ncomp):\n", - " cell = SimpleCell(nbranch, ncomp)\n", - " net = jx.Network([cell]*ncell)\n", - " return net" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 189, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of newly added trainable parameters: 3. Total number of trainable parameters: 3\n" - ] - } - ], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 222, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 223, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Array([[ 1, 2, -1],\n", - " [ 6, 7, -1],\n", - " [ 3, -1, -1]], dtype=int64)" - ] - }, - "execution_count": 223, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# global_params = [\"v\", \"radius\", \"length\", \"axial_resistivity\", \"capacitance\"]\n", - "# jaxnodes = {\"global\": {param: jnp.asarray(cell.nodes[param]) for param in global_params}}\n", - "\n", - "# # Add channel-specific nodes and update globals\n", - "# for channel in cell.channels:\n", - "# channel_dict = {}\n", - "# for param, value in {**channel.states, **channel.params}.items():\n", - "# if f\"{channel._name}_\" in param:\n", - "# channel_dict[param] = jnp.asarray(cell.nodes[param][channel.indices])\n", - "# else:\n", - "# jaxnodes[\"global\"][param] = jnp.asarray(cell.nodes[param])\n", - "# jaxnodes[channel._name] = channel_dict\n", - "\n", - "# # Update channel states\n", - "# for channel in cell.channels:\n", - "# # Combine channel-specific and global nodes\n", - "# channel_nodes = jaxnodes[channel._name].copy()\n", - "# channel_nodes.update({k: v[channel.indices] for k, v in jaxnodes[\"global\"].items()})\n", - " \n", - "# # Update states\n", - "# channel_states_updated = channel.update_states(\n", - "# channel_nodes, 0.025, channel_nodes[\"v\"], channel_nodes\n", - "# )\n", - " \n", - "# # Apply updates back to jaxnodes\n", - "# for key, val in channel_states_updated.items():\n", - "# mech_key = \"global\" if key in jaxnodes[\"global\"] else channel._name\n", - "# jaxnodes[mech_key][key] = jaxnodes[mech_key][key].at[channel.indices].set(val)\n", - "\n", - "# def _iter_states_params(self, params=False, states=False) -> Tuple[str, jnp.ndarray]:\n", - "# # TODO FROM #447: MAKE THIS WORK FOR VIEW?\n", - "\n", - "# # assert that either params or states is True\n", - "# assert params or states, \"Either params or states must be True.\"\n", - "# global_states = [\"v\"]\n", - "# morph_params = [\"radius\", \"length\", \"axial_resistivity\", \"capacitance\"]\n", - "\n", - "# for key in global_states + morph_params:\n", - "# yield \"global\", key, self._inds_of_state_param[key]\n", - " \n", - "# mechs = self.channels + self.synapses\n", - "# for mech in mechs:\n", - "# data = self.nodes if isinstance(mech, Channel) else self.edges\n", - "# params_states = mech.params if params else []\n", - "# params_states += mech.states if states else []\n", - "# for key in params_states:\n", - "# if f\"{mech._name}_\" not in key:\n", - "# yield \"global\", key, jnp.asarray(data.index)\n", - "# else:\n", - "# yield mech._name, key, mech.indices\n", - "\n", - "# def _get_all_states_params(\n", - "# self,\n", - "# pstate: List[Dict],\n", - "# voltage_solver=None,\n", - "# delta_t=None,\n", - "# all_params=None,\n", - "# params=False,\n", - "# states=False,\n", - "# ) -> Dict[str, jnp.ndarray]:\n", - "# states_params = {}\n", - "# pkeys = {k:[] for k in pstate}\n", - "# for i, p in enumerate(pstate):\n", - "# pkeys[p[\"key\"]] += [i]\n", - "\n", - "# for mech_key, key, _ in self._iter_states_params(params, states):\n", - "# jax_arrays = self.jaxnodes if key in self.nodes.columns else self.jaxedges\n", - "# states_params[mech_key][key] = jax_arrays[mech_key][key]\n", - "\n", - "# if key in pkeys:\n", - "# for i in pkeys[key]:\n", - "# # `inds` is of shape `(num_params, num_comps_per_param)`.\n", - "# # `set_param` is of shape `(num_params,)`\n", - "# # We need to unsqueeze `set_param` to make it `(num_params, 1)`\n", - "# # for the `.set()` to work. This is done with `[:, None]`.\n", - "# inds, set_param = pstate[i][\"indices\"], pstate[i][\"val\"]\n", - "# states_params[mech_key][key] = states_params[key].at[inds].set(set_param[:, None])\n", - "\n", - "# if params:\n", - "# # Compute conductance params and add them to the params dictionary.\n", - "# states_params[\"axial_conductances\"] = self._compute_axial_conductances(\n", - "# params=states_params\n", - "# )\n", - "\n", - "# if states:\n", - "# all_params = states_params if all_params is None and params else all_params\n", - "# for current in self.membrane_current_names:\n", - "# states_params[current] = jnp.zeros_like(states_params['v'])\n", - "# # Add to the states the initial current through every channel.\n", - "# states, _ = self._channel_currents(\n", - "# states_params, delta_t, self.channels, self.nodes, all_params\n", - "# )\n", - "\n", - "# # Add to the states the initial current through every synapse.\n", - "# states, _ = self._synapse_currents(\n", - "# states_params, self.synapses, all_params, delta_t, self.edges\n", - "# )\n", - "# return states_params\n", - " " - ] } ], "metadata": { From 50930f597640923644ef05a3d2998e0406e5aa39 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Wed, 28 May 2025 09:42:56 +0200 Subject: [PATCH 13/24] wip: save wip --- dev.ipynb | 202 ++++++++++++++++++++++++------------------------------ 1 file changed, 91 insertions(+), 111 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index b3feac06b..03901afc8 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 388, "metadata": {}, "outputs": [], "source": [ @@ -242,7 +242,56 @@ " break\n", " return branches\n", "\n", + "def compute_xyz(tree: MorphTree, length=1.0, spread=np.pi/8, spread_decay=0.9, twist=0.0, xy_only=True):\n", + " # TODO: Replace compute_xyz with this or vice versa, redundant!\n", + " G = tree.to_nx()\n", + " root = next(n for n, d in G.in_degree() if d == 0)\n", + " pos = {root: (0.0, 0.0, 0.0)}\n", + "\n", + " def recurse(node, depth=1, theta=0.0, phi=np.pi/2):\n", + " children = [n for n in G.successors(node) if n not in pos]\n", + " if not children: return\n", + " n = len(children)\n", + " curr_spread = spread * (spread_decay ** (depth - 1))\n", + " x0, y0, z0 = pos[node]\n", + " phi = np.pi/2 if xy_only else phi\n", + " base_theta = theta + depth * twist\n", + " if n == 1:\n", + " thetas, phis = [base_theta], [phi]\n", + " else:\n", + " if xy_only:\n", + " thetas = np.linspace(base_theta - curr_spread/2, base_theta + curr_spread/2, n)\n", + " phis = [phi] * n\n", + " else:\n", + " thetas = np.linspace(base_theta, base_theta + 2 * np.pi, n, endpoint=False)\n", + " phis = [phi - curr_spread] * n\n", + " for th, ph, child in zip(thetas, phis, children):\n", + " x = x0 + length * np.sin(ph) * np.cos(th)\n", + " y = y0 + length * np.sin(ph) * np.sin(th)\n", + " z = z0 + length * np.cos(ph) * (not xy_only)\n", + " pos[child] = (x, y, z)\n", + " recurse(child, depth + 1, th, ph)\n", + "\n", + " recurse(root, theta=0.0, phi=np.pi/2)\n", + " return pos\n", + "\n", + "def _add_missing_attrs(tree: MorphTree) -> MorphTree:\n", + " defaults = {\"id\": 0, \"r\": 1}\n", + " node_attr_keys = next(iter(tree.node_attrs.values())).keys()\n", + " xyz = compute_xyz(tree) if \"x\" not in node_attr_keys else {}\n", + " for n, (x, y, z) in xyz.items():\n", + " tree.node_attrs[n][\"x\"] = x\n", + " tree.node_attrs[n][\"y\"] = y\n", + " tree.node_attrs[n][\"z\"] = z\n", + "\n", + " missing_attrs = {k: v for k, v in defaults.items() if k not in node_attr_keys}\n", + " for n in tree.node_attrs:\n", + " tree.node_attrs[n].update(missing_attrs)\n", + " return tree\n", + "\n", "def compartmentalize(tree: MorphTree, num_comps: int = 1) -> MorphTree:\n", + " tree = _add_missing_attrs(tree)\n", + "\n", " branches = list_branches(tree)\n", " nodes_df = tree.to_pandas()[0].astype(float)\n", "\n", @@ -344,15 +393,6 @@ "\n", " return MorphTree.from_pandas(nodes_df, edge_df, pd.Series(global_attrs))\n", "\n", - "def _add_missing_attrs(tree: MorphTree) -> MorphTree:\n", - " nan = float(\"nan\")\n", - " defaults = {\"id\": 0, \"x\": nan, \"y\": nan, \"z\": nan, \"r\": 1}\n", - "\n", - " for i in tree.node_attrs:\n", - " for key in set(defaults.keys()).difference(tree.node_attrs.keys()):\n", - " tree.node_attrs[i][key] = defaults[key]\n", - " return tree\n", - "\n", "# def set_solve_order(tree: MorphTree, solve_order: List[int]) -> MorphTree:\n", "# # TODO: do we want to rm branchpoints and comp_edges?\n", "# return" @@ -362,118 +402,58 @@ "cell_type": "code", "execution_count": null, "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 390, + "metadata": {}, "outputs": [ { - "name": "stderr", - "output_type": "stream", - "text": [ - "/tmp/ipykernel_721647/3617806162.py:32: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.\n", - " z = z0 + length * np.cos(ph) * ~(xy_only)\n" + "ename": "ValueError", + "evalue": "setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (3,) + inhomogeneous part.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[390], line 14\u001b[0m\n\u001b[1;32m 3\u001b[0m edges \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 4\u001b[0m (\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m), (\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m2\u001b[39m), (\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m3\u001b[39m), \u001b[38;5;66;03m# root 0 branches to 1, 2, 3\u001b[39;00m\n\u001b[1;32m 5\u001b[0m (\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m4\u001b[39m), (\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m5\u001b[39m), \u001b[38;5;66;03m# node 1 branches to 4, 5\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 10\u001b[0m (\u001b[38;5;241m9\u001b[39m, \u001b[38;5;241m14\u001b[39m), (\u001b[38;5;241m9\u001b[39m, \u001b[38;5;241m15\u001b[39m), (\u001b[38;5;241m9\u001b[39m, \u001b[38;5;241m16\u001b[39m) \u001b[38;5;66;03m# node 9 branches to 14, 15, 16\u001b[39;00m\n\u001b[1;32m 11\u001b[0m ]\n\u001b[1;32m 12\u001b[0m G\u001b[38;5;241m.\u001b[39madd_edges_from(edges)\n\u001b[0;32m---> 14\u001b[0m \u001b[43mcompartmentalize\u001b[49m\u001b[43m(\u001b[49m\u001b[43mMorphTree\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_nx\u001b[49m\u001b[43m(\u001b[49m\u001b[43mG\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnum_comps\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m2\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mplot()\n", + "Cell \u001b[0;32mIn[388], line 289\u001b[0m, in \u001b[0;36mcompartmentalize\u001b[0;34m(tree, num_comps)\u001b[0m\n\u001b[1;32m 287\u001b[0m comp_inds \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39marray([branch_tips[\u001b[38;5;241m0\u001b[39m], \u001b[38;5;241m*\u001b[39mcomp_inds, branch_tips[\u001b[38;5;241m1\u001b[39m]])\n\u001b[1;32m 288\u001b[0m comp_attrs \u001b[38;5;241m=\u001b[39m [branch_tip_attrs[\u001b[38;5;241m0\u001b[39m]] \u001b[38;5;241m+\u001b[39m [comp_attrs] \u001b[38;5;241m+\u001b[39m [branch_tip_attrs[\u001b[38;5;241m1\u001b[39m]]\n\u001b[0;32m--> 289\u001b[0m comp_attrs \u001b[38;5;241m=\u001b[39m \u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhstack\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcomp_inds\u001b[49m\u001b[43m[\u001b[49m\u001b[43m:\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcomp_attrs\u001b[49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 291\u001b[0m \u001b[38;5;66;03m# Interpolate xyzr coordinates and combine with attributes\u001b[39;00m\n\u001b[1;32m 292\u001b[0m x \u001b[38;5;241m=\u001b[39m jnp\u001b[38;5;241m.\u001b[39marray([\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m+\u001b[39m comp_locs \u001b[38;5;241m+\u001b[39m [branch_len]) \u001b[38;5;66;03m# 0, branch_len = branchpoints\u001b[39;00m\n", + "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/numpy/_core/shape_base.py:360\u001b[0m, in \u001b[0;36mhstack\u001b[0;34m(tup, dtype, casting)\u001b[0m\n\u001b[1;32m 295\u001b[0m \u001b[38;5;129m@array_function_dispatch\u001b[39m(_vhstack_dispatcher)\n\u001b[1;32m 296\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mhstack\u001b[39m(tup, \u001b[38;5;241m*\u001b[39m, dtype\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, casting\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msame_kind\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 297\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 298\u001b[0m \u001b[38;5;124;03m Stack arrays in sequence horizontally (column wise).\u001b[39;00m\n\u001b[1;32m 299\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 358\u001b[0m \n\u001b[1;32m 359\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 360\u001b[0m arrs \u001b[38;5;241m=\u001b[39m \u001b[43matleast_1d\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mtup\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 361\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(arrs, \u001b[38;5;28mtuple\u001b[39m):\n\u001b[1;32m 362\u001b[0m arrs \u001b[38;5;241m=\u001b[39m (arrs,)\n", + "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/numpy/_core/shape_base.py:69\u001b[0m, in \u001b[0;36matleast_1d\u001b[0;34m(*arys)\u001b[0m\n\u001b[1;32m 67\u001b[0m res \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m 68\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m ary \u001b[38;5;129;01min\u001b[39;00m arys:\n\u001b[0;32m---> 69\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43masanyarray\u001b[49m\u001b[43m(\u001b[49m\u001b[43mary\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 70\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m result\u001b[38;5;241m.\u001b[39mndim \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 71\u001b[0m result \u001b[38;5;241m=\u001b[39m result\u001b[38;5;241m.\u001b[39mreshape(\u001b[38;5;241m1\u001b[39m)\n", + "\u001b[0;31mValueError\u001b[0m: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (3,) + inhomogeneous part." ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxYAAAMWCAYAAABsvhCnAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAApbxJREFUeJzs3Xd41fXd//HnOTnZey+yCCNhD9kiICio7GFttVZrsXerv7auuqjetXXe1rbuet84UCkucCLI3omI7BEgzCQkZJA9zvr+/kBOSwUETpJzEl6P6+Iy5+Q73t9jznidzzIZhmEgIiIiIiLiBrOnCxARERERkbZPwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxERERERcZuChYiIiIiIuE3BQkRERERE3KZgISIiIiIiblOwEBERERERtylYiIiIiIiI2xQsRERERETEbQoWIiIiIiLiNgULERERERFxm4KFiIiIiIi4TcFCRERERETcpmAhIiIiIiJuU7AQERERERG3KViIiIiIiIjbFCxERERERMRtChYiIiIiIuI2BQsREREREXGbgoWIiIiIiLhNwUJERERERNymYCEiIiIiIm5TsBAREREREbcpWIiIiIiIiNsULERERERExG0KFiIiIiIi4jYFCxER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dihYiIiIiJwnwzBYv3696wO3j48PV1xxBU888cQ5V7Jui+68807uvPPOM/5u5cqV37tvxowZzJgx46LP17Vr14veV7yDgoWIiIjIebBarfzjH//grbfeoqGhgaCgIP7rv/6LW2+99bRv7+XC5Ofn88Ybb5Cfn8/f//534uLi+PLLL0lNTW03LUCXCj0LRERERH5AcXExd955J6+99hoNDQ0kJyfz2muvcdtttylUuGHVqlX07NmT3Nxc5s+fT21tLQBbt27l0Ucf9XB1cqH0TBARERE5C8MwWLduHTfffDPr1q3DZDJx+eWXM2/ePPr27evp8tq8Bx54gD//+c8sWbIEPz8/1/1XXnklOTk5HqxMLoa6QomIiIicQVNTE7Nnz+bNN9+krq6OoKAgbr31Vv7rv/5LrRTNZPv27cydO/d798fFxVFWVuaBisQdChYiIiIi/6GkpITHHnuMNWvW4HA4SEpK4o9//CNDhw71dGntSkREBMeOHSMjI+O0+zdv3kxycrKHqpKLpbgtIiIi8h3DMNiwYQO33nqra+ajgQMH8u677ypUtIAbbriB+++/n+LiYkwmE06nk3Xr1nHvvfdy8803e7o8uUBqsRARERHhZNenN998kzfeeIOamhoCAwP58Y9/zG9/+1ssFn1kaglPPPEEd9xxBykpKTgcDrp164bD4eAnP/kJs2bN8nR5coH0LBEREZFLXnFxMU8++SQrV67EbreTkJDAww8/zJVXXunp0to1Pz8//vd//5dHHnmE7du3U1tbS9++fencubOnS5OLoGAhIiIilyzDMMjJyeHJJ58kPz8fi8VCv379ePLJJ+nQoYOny7tkpKSkkJKS4rp99OhRHn30UV5//XUPViUXSmMsRERE5JLU2NjI//3f/3HPPfeQn59PYGAg119/PbNnz1ao8LCKigreeustT5chF0gtFiIiInLJKSoq4i9/+QvLli3DbrcTHx/PfffdxzXXXOPp0i4Jn3766Tl/f+DAgVaqRJqTgoWIiIhcMgzDIDc3l2eeeYa9e/fi4+NDz549efzxx+nYsaOny7tkTJ48GZPJhGEYZ93GZDK1YkXSHNQVSkRERC4JDQ0NvP7669x3333k5eURGBjI5MmTef311xUqWlliYiLz58/H6XSe8d+3337r6RLlIqjFQkRERNq9wsJCnn/+eZYsWYLVaiUu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wapVq/j8889Zs2YNdrudpKQkbrjhBn72s59pJj4vVFxcTFxc3Gn3WSwWoqKizjnt709+8hPS0tJISkpi27Zt3H///eTl5TF//vyWLlk8RMFCREREWkVtbS3vvPMOS5YsYevWrQQHB5ORkcG9997LwIEDPV3eJeeBBx7g6aefPuc2u3fvvujj33777a6fe/bsSWJiIqNHjyY/P5/MzMyLPq54LwULERERaXEHDx7ko48+YteuXRQVFREVFUWfPn2YNWsWsbGxni7vknTPPfdwyy23nHObjh07kpCQwPHjx0+73263U1FRcUHjJwYNGgSc7AanYNE+KViIiIhIi3E4HKxcuZKPPvqIdevWYTabSUxMZMqUKdx+++0tuoaDnFtsbOx5hbohQ4ZQWVnJpk2bXGv3LF++HKfT6QoL52PLli0AJCYmXlS94v0ULERERKRFVFZW8sknn7By5Uq+/vprLBYLHTt25He/+x3Dhw/3dHlynrKzsxk3bhwzZ87k1VdfxWazceedd3LDDTe4ZoQqLCxk9OjRzJkzh4EDB5Kfn8/cuXO59tpriY6OZtu2bdx1111cccUVGpzfjilYiIiISLPbu3cvH3/8MStXruTo0aOEh4eTmprKc889d87pScU7vfvuu9x5552MHj0as9nMtGnTeP75512/t9ls5OXluWZ98vPzY+nSpfztb3+jrq6OlJQUpk2bxqxZszx1CdIKFCxERESk2TgcDpYvX87SpUtZs2YNjY2NJCQkMGzYMK677jqFijYqKirqnIvhpaenYxiG63ZKSgqrVq1qjdLEiyhYiIiISLM4ceIEn3zyCevXryc3N5egoCBSU1P59a9/TY8ePb43AFhE2hcFCxEREXFbXl4en332GWvWrOHgwYNERUXRuXNnHn74YdLT0ykqKvJ0iSLSwhQsRERE5KLZ7XaWLVvG6tWrWbVqFfX19cTHxzNq1CjuvvtuAgICPF2iiLQSBQsRERG5KBUVFXzyySd8/fXX5OTkEBAQQIcOHfjFL37BxIkTPV2eiLQyBQsRERG5YLt37+bzzz8nJyeHffv2ERUVRVpaGg899BBdu3b1dHki4gEKFiIiInLe7HY7S5cuZe3ataxZs4aamhoSEhIYMmQIv//97wkODvZ0iSLiIQoWIiIicl7Ky8v5+OOP2bJlC+vXr8fPz4/k5GR++tOfMmPG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7t27ycrKct0uLCxk3LhxzJgxg5kzZ55z39tvv931c8+ePUlMTGT06NHk5+eTmanXvvZIwUIumMVioVu3boSGhrJy5Uq6du2qICFtyocffsicOXOw2WyEh4dz11130b17d/7vxaPckrUSi/niw4Xx3X8dMVdispZ+NzDchmHyxRmajSNqMLaUmzRQW0Q87p577uGWW2455zanui4DFBUVMWrUKIYOHcprr1342LRBgwYBJ1s8FCzaJwULuShRUVEYhvHDG4p4kfr6ep555hlyc3MB6NKlC7NmzaKiooIbb7yR/PwDvB2dyLsza0gJrz1rq8PZGJjBbPl+9ybDqRW1RcTrxMbGEhsbe17bFhYWMmrUKPr3788bb7xxUV2bTy2OmJiYeMH7StugdzoRuSTs27ePX//61+Tm5mIymZg0aRLPPfccq1ev5uc//zn79+/H19eXoVffTOCMg9RfNhebz8nFAH8oQ7taKaKHUDcy9/tjJhQqRKQNKywsZOTIkaSmpvLss89SWlpKcXExxcXFp22TlZXF119/DUB+fj5/+tOf2LRpE4cOHeLTTz/l5ptv5oorrqBXr16euhRpYWqxEJF275NPPuH111/HarUSGhrKb3/7W3r37s2jjz7KwoULaWpqIjo6mvvuu4/x48fjcDj4YquFb7f8Ap/qrQyK2cWg1CpiAqowmwxXS4aBCWdwJo7YK9W9SUTarSVLlrB//372799Phw4dTvvdqd4LNpuNvLw816xPfn5+LF26lL/97W/U1dWRkpLCtGnTmDVrVqvXL61HwUJE2q3GxkaeffZZ1q1bB5xchPEPf/gDVVVV/OIXv2DXrl04nU66devGY489RnZ2NidOnODjjz+mqKiI/Px8fH0jsIfegD1qEFdeeSVmE2Ayc7ykmMNHjjJgwADPXqSISAu75ZZbfnAsRnp6+mldpFNSUr636ra0fwoWItIuHThwgMcff5yioiJMJhPXXnstv/zlL1m4cCHPP/88JSUl+Pr6Mm7cOB544AGioqLYt28fn332GXV1deTn5xMbG0tUVBRXXXUVl1122eknUPcmERGR0yhYiEi7s3DhQl577TWampoIDg7mzjvvZMCAATz11FN8/vnn1NbWEhkZyc9+9jN+9rOfYbFYWL58OTk5OTQ1NVFYWEhqaiqhoaFMnjyZzp07e/qSREREvJ6ChYi0G01NTfz1r391Nb+np6cza9YsGhoauOOOO9i6dSs2m41OnTpx9913c8UVV1BbW8v777/PkSNHqKuro7q6mvT0dMLCwpgxY4ZmLxERETlPChYi0i4cPnyYxx9/nKNHjwJw9dVXc8cdd7B48WJefvllCgoK8PHxYcSIEdx9991kZma6Ziqpra2ltrYWh8NBYmIisbGxzJgxg4iICM9elIiISBuiYCEibd6SJUt45ZVXaGhoIDAwkF//+tcMHjyYv/zlL3z55ZeUl5cTERHBpEmTmDlzJhEREaxbt47Vq1djGAZNTU1YLBZCQkJIT09n6tSpBAQEePqyRERE2hQFCxFps6xWKy+88AJLly4FTs5CMmvWLGw2G3fddRdbt26lvr6ejh078tOf/pTJkydjt9t5//33yc/PB8BkMmGxWPDx8aFXr15cc801+Pj4ePKyRERE2iQFCxFpkwoKCvjzn//M4cOHARg1ahS//e1vWbp0Ka+99hpHjhzBMAwGDhzIL3/5SwYOHEhRURELFiyguroak8lEYGAg9fX1ri5SQ4cOxWS6kLW2RURE5BQFCxFpc1asWMGLL75IfX09AQEB3H777QwfPpznn3+eRYsWcfz4ccLCwrjyyiv5+c9/Tnp6Ops2bWLZsmU4HA6Cg4Px8fGhuroaHx8frrvuOnr06OHpyxIREWnTFCxEpM2w2+28/PLLLFq0CMMwSEpKYtasWTgcDu677z62b99OVVUVqampjB8/nh//+McEBgby8ccfs3v3bgCSk5Oprq6murqawMBApk6dSlpamoevTEREpO1TsBCRNuHYsWM8/vjjrrERw4cP53e/+x2rVq1i9uzZHD58GJvNRv/+/Zk8eTLXXXcdJ06cYN68eVRUVGA2m+nRowd79+6lsbGRiIgIfvSjHxEdHe3hKxMREWkfFCxExOutXbuWv//979TW1uLn58cvfvELRo0axcsvv8zSpUspLi4mKCiIkSNHcv3113PZZZexfft2Fi9ejM1mIywsjG7durFx40YcDgfJyclMnz6d4OBgT1+aiIhIu6FgISJey+Fw8Nprr/HZZ59hGAYJCQk8/PDDADz44IPs2LGDiooKkpKSGDlyJDfccANJSUl8+eWXbNmyBYCOHTsSFxdHTk4OAF27dmXixIn4+vp66rJERETaJQULEfFKpaWl/OlPf2Lfvn0ADB48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jJxOZ6XH9Pb21pw5czRx4kTdddddzBrlJswKBQAAgFoTFxenuLg4SWUDucvXmThx4oSksq5RgwYNklTWNWrfvn1q166dli9frpdeekmPPPKIvLy89PXXX8sYo44dOyomJkanT5/WP//5TyUmJiohIUERERFasWKFxowZo9LSUoWHh7vKEBYWpgEDBuj111+XJGaNqicECwAAANSJqVOnauzYserfv7/atWsnqequUe3bt1dBQYHuuOMO1/bt27dXUFCQgoKCFBMTow4dOujf//63ZsyYoY8//liS1LZtW40YMcJ1XLvdroCAAIWFhdXr673cMcYCHmPu3LmKiYlRSEiIQkJCNGjQIH3xxRdV7rN48WJ17dpV/v7+6tWrlz7//PN6Kq1nePbZZzVgwAAFBwerZcuWGj16tNLS0qrcZ/78+bLZbBVu/v7+9VRi97uUOpM411avXq2bbrpJERERstlsF+27/O233553ntlsNmVmZtZPgT1ATetMKqu3vn37ys/PT506ddL8+fPrvJye6JVXXlG7du3k7++v2NhY17Sklbncr2nlalJnUv1d026//XbNnj1bjz32mK6//npJ0vTp09WqVSsVFxfr5MmTstlsrgAwb948SdKCBQsUHh7uus2ePVuS5O/vLz8/P33wwQeKjo7WsmXLJElvvfVWhVaJo0ePatmyZerSpYsmTZp0wcX9ULsIFvAYkZGRmjlzprZs2aLNmzfr17/+tW6++Wbt2LGj0u0TExP1hz/8QePHj9e2bds0evRojR49WqmpqfVccvdJSEjQ5MmTtX79en399dcqKSlxzQVelZCQENfsGhkZGTpw4EA9ldj9LqXOONekvLw8XXHFFXrllVdqtF9aWlqFc61ly5Z1VELPU9M627dvn0aNGqVrrrlGSUlJuu+++zRhwgR9+eWXdVxSz/Lhhx9q6tSpmjFjhrZu3aorrrhCI0aM0LFjxy64z+V8TZNqXmf1fU2Li4vTgQMHVFxcrIEDB1bZNWr//v26//77NXDgQNcsUcYYPf7445LKZp4KDQ3VX/7yF61Zs0alpaVq2rSpkpKSXMcbOnSobDabHn/8cc2aNUsJCQm64YYb5HA46uT14SwG8GBNmjQxb775ZqWP3XbbbWbUqFEV7ouNjTUTJ06sj6J5pGPHjhlJJiEh4YLbvP3226Zx48b1VygPV50641yrSJL55JNPqtxm1apVRpI5depUvZTJ01Wnzh544AHTo0ePCvfdfvvtZsSIEXVYMs8zcOBAM3nyZNfvDofDREREmGeffbbS7bmm1bzO3HlNW7RokfHz8zPz58833377rZFkgoKCTGZmpjHGmDFjxpjY2FgzcOBAY4wxTzzxhPnyyy9Nenq62bJli/n9739v/P39zY4dO8y9995revXqZWbOnGlCQ0PN0qVLTXJysrn55ptN+/btTUFBgTHGmPT0dCPJrFixos5f3+WOFgt4JIfDoUWLFikvL8/1Lca51q1bp+uuu67CfSNGjNC6devqo4ge6fTp05Kkpk2bVrldbm6u2rZtq6ioqCpbhS4H1akzzrVL17t3b4WHh+v666/X2rVr3V0cj8Z5VrbA2pYtWyrUg91u13XXXVdlPVzO17RLqTN3nmtVdY2SpB9//FEnTpxwdY06deqU7rnnHnXr1k0jR45UTk6OEhMT1bZtWy1atEjjx4/XAw88oL/+9a+69957NWDAAOXm5io+Pt7VJa5Dhw5q3ry59u7dW+ev73JHsIBHSUlJUVBQkPz8/PTnP/9Zn3zyibp3717ptpmZma4LUblWrVpdVn24z+Z0OnXfffdpyJAh6tmz5wW369Kli/7zn/9o6dKlev/99+V0OjV48GAdOnSoHkvrGapbZ5xrNRceHq7XXntN//3vf/Xf//5XUVFRGjZsmGuxK5zvQudZTk6OCgoK3FSq+nXixAk5HI4avd8u92vapdSZu69pF+oaJUkrV65UYWGh60vFF198UQcOHFBRUZEyMzP12WefqU+fPlq8eLGKior0pz/9STabTU8++aQyMzNVWFioFStWKDo62vWchw4d0smTJyvMGoW6waxQ8ChdunRRUlKSTp8+rSVLlmjs2LFKSEi4YLjAzyZPnqzU1FStWbOmyu0GDRpUoRVo8ODB6tatm+bNm6ennnqqrovpUapbZ6i5Ll26qEuXLq7fBw8erPT0dL344ot677333Fgy/NJwTWvYzp41auDAgXrppZeUl5fnmjXqzjvvVOvWrfXss89W2O+tt97S6NGj1axZswr35+bm6oknntCtt96qsLAwpaen64EHHlCnTp0qzBqFukGwgEfx9fVVp06dJEn9+vXTpk2b9PLLL7tmiThbWFiYjh49WuG+o0ePXpZTy8XFxWn58uVavXq1IiMja7Svj4+P+vTpc9k1EdekzjjXasfAgQMJcVW40HkWEhKigIAAN5WqfjVv3lxeXl6W3m+X2zXtUurMk65pt99+u44fP67HHntMmZmZ6t27t+Lj4yt0jbLbK3awSUtL05o1a/TVV1+d93xeXl5KTk7WO++8o+zsbEVERGj48OF66qmnWMuiHtAVCh7N6XSqqKio0scGDRqkb775psJ9X3/99QXHZPwSGWMUFxenTz75RCtXrlT79u1r/BwOh0MpKSmXTRPxpdQZ51rtSEpKumzOs0vBeVb25VK/fv0q1IPT6dQ333xT7Xq43K5pl1JnnnaulXeNKioq0oYNGxQbG+t67Ntvvz1v2uUuXbrIGOMao3G2gIAAffnllzp27JiKi4u1f/9+vf766+d1/UIdcfPgccDloYceMgkJCWbfvn0mOTnZPPTQQ8Zms5mvvvrKGFM2U8RDDz3k2n7t2rXG29vbzJ492+zatcvMmDHD+Pj4mJSUFHe9hHo3adIk07hxY/Ptt9+ajIwM1y0/P9+1zbn1VtUMG5eDS6kzzjVjzpw5Y7Zt22a2bdtmJJkXXnjBbNu2zRw4cMAYU/b+HTNmjGv7F1980Xz66admz549JiUlxUyZMsXY7fbLalaWmtbZDz/8YAIDA839999vdu3aZV555RXj5eVl4uPj3fUS3OLsWYN27txp7r33XhMaGlph1iCuaRXVtM64pqGuECzgMe6++27Ttm1b4+vra1q0aGGuvfZaV6gwxpirr77ajB07tsI+H330kYmOjja+vr6mR48e5rPPPqvnUruXpEpvb7/9tmubc+vtvvvuM23atDG+vr6mVatWZuTIkWbr1q31X3g3uZQ6M4ZzrXz62HNv5fU0duxYc/XVV7u2nzVrlunYsaPx9/c3TZs2NcOGDTMrV650T+HdpKZ1Vr5P7969ja+vr+nQoUOF8/Jy8u9//9t1nRo4cKBZv3696zGuaZWrSZ0ZwzUNdcNmjDH11z4CAAAA4JeIMRYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwLL/D4PrqESWqjIiAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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mqlTp1K9enVHl1ai6TaoiIiIMGfOHCZMmMDp06eZOHEiL774Ys7VneIw+e+2KiIiIi7n2LFjTJgwgdmzZzNo0CBiYmKoX7++o8uSK+g2qIiISAmUmZnJxx9/TNOmTdmwYQO///47UVFRCmpOSCNrIiIiJczKlSt57LHHiI2NZcKECbz99tv4+fk5uizJg0bWRERESohz587x4IMP0rNnT8qUKcOmTZv4/PPPFdScnEbWREREXJzVauXHH3/kpZdewmq18t133/Hwww/b20WJc9P/JRERERe2Y8cOevbsycMPP0xwcDB79+7l0UcfVVArRvR/SkRExAUlJyfz/PPP07ZtW+Lj41myZAk//fQTVatWdXRpcpN0G1RERMSFGIbBrFmzmDBhAufPn+fdd9/lueeew8vLy9GlyS3SyJqIiIiLOHz4MEOHDmXUqFG0bt2aXbt28corryioFXMKayIiIsVcRkYGH3zwAc2bN2fbtm3MmDGDuXPnUrduXUeXJgVAt0FFRESKsaVLl/L444+zb98+nnnmGd588018fX0dXZYUII2siYiIFENxcXHcf//99O3blwoVKrB582Y++eQTBTUXpJE1ERGRYsRqtfLf//6Xl19+GTc3N77//nvGjRunrThcmP7PioiIFBNbtmyhW7dujB8/npEjR7J3714eeughBTUXp/+7IiIiTi4pKYlnnnmGDh06kJyczIoVK/jxxx+pXLmyo0uTIqDboCIiIk7KMAwsFgtPP/00Fy9e5MMPP+Tpp5/G09PT0aUVHsMKJo0lXUlhTURExAkdPHiQf/zjHyxYsIARI0bwxRdfUKdOHUeXVfAubIZDkyFuBSTGgjUT3DzBrxlU7Qn1xkHFdo6u0qFMhmEYji5CREREbNLT0/noo494//33qV69Ol999RVDhw51dFkFL+kArH0Izi4HkwcYWdcec/nxKr2gyw9QtkHR1+kEFNZEREScRExMDI8//jiHDh3iueee4/XXX6dMmTKOLqvgHZkGax8EIzv3kHY1kweY3KHLZPC/p/DrczIKayIiIg52+vRpnnvuOaZNm0avXr3417/+RfPmzR1dVqFI3vUjn7z+EOsOwvqDEJ8Ckx+BB3rnPO6B7+CnFde+vnG9Guw5eLJoinUSmrMmIiLiINnZ2Xz33XdMnDgRT09PpkyZwv3334/JZHJ0aYUjcT/n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kp2dzYoVK+wB7fTp09SqVcse0Lp166aA5oIU1kRExKVlZmby+eef8/bbb1O+fHnCw8MZPXp0sdkzLSsri2XLlmGxWJgxYwZxcXHUrl2be+65B7PZTJcuXXBz0wpKV6bboCIi4rJWrFjBY489xu7du3nqqad4++23KVu2rKPLuqHMzEyWLFlCeHg4M2fO5Pz58/j7+xMSEoLZbKZjx47FJmzK7dPImoiIuJyzZ8/y4osvMmXKFLp06cKmTZto06aNo8u6royMDGJiYggPD2fWrFnEx8dTv359Hn74YcxmM+3atVNAK6E0siYiIi7DarXy448/8tJLL2EYBh9++CF///vfnfY2YXp6OgsXLsRisTB79mwSEhJo1KiRfQStdevWCmiisCYiIq5h+/btjB8/njVr1nD//ffzySefULVqVUeXdY1Lly6xYMECLBYLc+bMISkpiWbNmmE2mzGbzbRo0UIBTXLQbVARESnWkpOTeeutt/jnP/9Jo0aNWLp0Kb1793Z0WTmkpqYyb948LBYLERERJCcn07JlS55//nnMZjPNmjVzdInixDSyJiIixZJhGMycOZOnnnqK8+fP88Ybb/Dss886Tfuk5ORkoqKisFgsREZGkpqaSps2bQgJCWH06NE0btzY0SVKMaGwJiIixc7hw4d54okniIqKIjg4mK+++gp/f39Hl0VSUhIRERGEh4czb9480tLS6NChA2azmdGjR9OgQQNHlyjFkMKaiIgUGxkZGXz66ae8++67VKlShS+//JLhw4c7dI5XQkICc+fOJTw8nAULFpCenk7nzp3tAa1u3boOq01cg8KaiIgUC0uXLuWxxx5j//79PPPMM7z55pv4+vo6pJb4+Hhmz56NxWJh4cKFZGZm0rVrV/stzjp16jikLnFNCmsiIuLU4uLieP755/n555/p3r073377LS1btizyOs6fP8+sWbOwWCxER0eTnZ1Njx497CNotWrVKvKapGRQWBMREadktVr5z3/+wyuvvIK7uzsff/wxDzzwQJHumRYXF2cPaIsXL8YwDHr16kVISAgjR46kRo0aRVaLlFwKayIi4nS2bNnC+PHjWb9+PQ8++CAfffQRlStXLpL3Pn36NDNnzsRisbB06VJMJhN9+vQhJCSEESNGUK1atSKpQ+Qy7bMmIiJOIzExkddff52vv/6aZs2asWLFCnr0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3Xf89ttvNGvWjFmzZjm6LBERuYrCmkgJ5ubmxqOPPkpsbCzt27dn5MiR3HXXXZw5c8bRpYmIyJ8U1kSEO+64gzlz5vDLL7+wZMkSmjZtyv/+9z+1rBIRcQIKayIC2FpW3X333ezevZshQ4bwt7/9jcGDB3P06FFHlyYiUqIprIlIDpUrVyYsLIyIiAh27dpF8+bN+eqrr7BarY4uTUSkRFJYE5FcBQUFsWvXLu6//34mTJhAz5492b17t6PLEhEpcRTWRCRPfn5+/Otf/2LZsmWcPXuWNm3aMGnSJDIzMx1dmohIiaFNcUUkXy5dusQ777zDJ598QvPmzfnxxx9p3769o8sSEXF5GlkTkXwpVaoUH3zwAevXr8fNzY1OnTrx4osvqmWViEgh08iaiNy0zMxMPv30U95++21q167Nf//7X/r06ePoskREXJJG1kTkpnl6evLKK6+wdetWqlWrRt++fRk/fjwJCQmOLk1ExOUorInILWvSpAnLly/nm2++YerUqTRv3py5c+c6uiwREZeisCYit8XNzY3HH3+cXbt20apVK4YNG8Y999xDXFyco0sTEXEJCmsiUiDq1KlDZGQkP//8M4sWLaJZs2ZMnTpVLatERG6TwpqIFBiTyURoaCixsbH079+f0NBQgoODOX78uKNLExEpthTWRKTAVa1alV9++YXZs2ezdetWmjVrxr/+9S+1rBIRuQUKayJSaIYNG0ZsbCxjx47lH//4B3369GHv3r2OLktEpFhRWBORQlWuXDn+/e9/s3jxYk6ePEnr1q358MMP1bJKRCSfFNZEpEj07duX7du3M2HCBCZOnEinTp3YsmWLo8sSEXF6CmsiUmRKly7Nxx9/zLp168jOzqZjx4688sorXLp0ydGliYg4LbWbEhGHyMjI4OOPP+bdd9/F39+f77//np49ezq6LBERp6ORNRFxCC8vL1577TW2bNlCpUqV6NWrF//4xz9ITEx0dGkiIk5FYU1EHKpZs2asWLGCL774gilTptC8eXOioqIcXZaIiNNQWBMRh3N3d2fChAns2rWLZs2aERQURGhoKOfOnXN0aSIiDqewJiJOw9/fn/nz5zNlyhSioqJo2rQpv/76q1pWiUiJprAmIk7FZDLxt7/9jdjYWPr06cM999zD8OHD+eOPPxxdmoiIQyisiYhTql69OuHh4cyYMYMNGzbQvHlz/v3vf6tllYiUOAprIuLURo4cSWxsLCEhIYwfP55+/fqxf/9+R5clIlJkFNZExOlVqFCB77//nkWLFnHs2DFatWrFJ598QlZWlqNLExEpdAprIlJsBAYGsmPHDh577DFefvllunTpwrZt2xxdlohIoVJYE5FipUyZMvzf//0fq1evJi0tjQ4dOvD666+Tnp7u6NJERAqF2k2JSLGVkZHBBx98wKRJk6hfvz7ff/893bt3d3RZIiIFSiNrIlJseXl58eabb7J582b8/Pzo2bMnEyZMIDk52dGliYgUGIU1ESn2WrRowerVq/nss8/44YcfaN68OQsWLHB0WSIiBUJhTURcgru7O8888ww7duygYcOGDBo0iL/97W+cP3/e0aWJiNwWhTURcSn16tVj0aJF/PDDD8yePZtmzZoRHh6ullUiUmwprImIyzGZTDz44IPExsbSrVs37rrrLkaNGsXJkycdXZqIyE1TWBMRl1WzZk1mzJhBeHg4q1evplmzZnz//fcaZRORYkVhTURcmslkwmw2s3v3bkaOHMnDDz9MYGAgBw8edHRpIiL5orAmIiVCxYoVmTx5MgsWLODgwYO0bNmS//u//yM7O9vRpYmIXJfCmoiUKAMGDGDnzp08/PDDPP/883Tr1o2dO3c6uiwRkTwprIlIiePr68sXX3zBypUrSUxMpF27drz55ptqWSUiTkntpkSkREtPT2fSpEl88MEHNGrUiB9++IEuXbo4uiwRETuNrIlIiebt7c0777zDpk2bKF26NN26deOZZ54hJSXF0aWJiAAaWRMRscvKyuKf//wnr7/+OtWrV+e///0vgYGBji5LREo4jayJiPzJw8OD559/nh07duDv70///v156KGHiI+Pd3RpIlKCKayJiFylQYMGxMTE8J///AeLxUKzZs2YMWOGo8sSkRJKYU1EJBdubm48/PDDxMbG0qlTJ0aPHo3ZbOb06dOOLk1EShiFNRGR66hVqxazZs3it99+Y/ny5TRt2pQpU6aoZZWIFBmFNRGRGzCZTNx1113s3r2boUOHMm7cOAYOHMjhw4cdXZqIlAAKayIi+VSpUiX+97//ERUVxZ49e2jRogVffPGFWlaJSKFSWBMRuUmDBw9m165djBs3jqeffpoePXoQGxvr6LJExEUprImI3IKyZcvy9ddfs2LFCuLj42nb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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" } ], "source": [ - "def create_xyz_tree(\n", - " G, \n", - " length=1.0, \n", - " spread=np.pi/8,\n", - " spread_decay=0.9, \n", - " xy_only=False,\n", - " twist=0.0\n", - "):\n", - " root = next(n for n, d in G.in_degree() if d == 0)\n", - " pos = {root: (0.0, 0.0, 0.0)}\n", - "\n", - " def recurse(node, depth=1, theta=0.0, phi=np.pi/2):\n", - " children = [n for n in G.successors(node) if n not in pos]\n", - " if not children: return\n", - " n = len(children)\n", - " curr_spread = spread * (spread_decay ** (depth - 1))\n", - " x0, y0, z0 = pos[node]\n", - " phi = np.pi/2 if xy_only else phi\n", - " base_theta = theta + depth * twist\n", - " if n == 1:\n", - " thetas, phis = [base_theta], [phi]\n", - " else:\n", - " if xy_only:\n", - " thetas = np.linspace(base_theta - curr_spread/2, base_theta + curr_spread/2, n)\n", - " phis = [phi] * n\n", - " else:\n", - " thetas = np.linspace(base_theta, base_theta + 2 * np.pi, n, endpoint=False)\n", - " phis = [phi - curr_spread] * n\n", - " for th, ph, child in zip(thetas, phis, children):\n", - " x = x0 + length * np.sin(ph) * np.cos(th)\n", - " y = y0 + length * np.sin(ph) * np.sin(th)\n", - " z = z0 + length * np.cos(ph) * (not xy_only)\n", - " pos[child] = (x, y, z)\n", - " recurse(child, depth + 1, th, ph)\n", - "\n", - " recurse(root, theta=0.0, phi=np.pi/2)\n", - " for n, (x, y, z) in pos.items():\n", - " G.nodes[n].update({'x': float(x), 'y': float(y), 'z': float(z)})\n", - " return G\n", - "\n", - "# Create a simple tree\n", + "# TODO: FIX THIS\n", "G = nx.DiGraph()\n", "edges = [\n", - " (0, 1), (0, 2), (0, 3), # root 0 branches to 1, 2, 3\n", - " (1, 4), (1, 5), # node 1 branches to 4, 5\n", - " (2, 6), (2, 7), (2, 8), # node 2 branches to 6, 7, 8\n", - " (3, 9), # node 3 branches to 9\n", - " (4, 10), (4, 11), # node 4 branches to 10, 11\n", - " (7, 12), (7, 13), # node 7 branches to 12, 13\n", - " (9, 14), (9, 15), (9, 16) # node 9 branches to 14, 15, 16\n", + " (0, 1), (0, 2), (0, 3),\n", + " (1, 4), (1, 5),\n", + " (2, 6), (2, 7), (2, 8),\n", + " (3, 9),\n", + " (4, 10), (4, 11),\n", + " (7, 12), (7, 13),\n", + " (9, 14), (9, 15), (9, 16)\n", "]\n", "G.add_edges_from(edges)\n", "\n", - "G = create_xyz_tree(G, xy_only=True)\n", - "\n", - "# Create a 3D plot\n", - "fig = plt.figure(figsize=(10, 10))\n", - "ax = fig.add_subplot(111, projection='3d')\n", - "\n", - "# Get 3D positions\n", - "pos_3d = {n: (G.nodes[n]['x'], G.nodes[n]['y'], G.nodes[n]['z']) for n in G.nodes}\n", - "\n", - "# Plot nodes\n", - "for node, (x, y, z) in pos_3d.items():\n", - " ax.scatter(x, y, z, c='orange', s=200)\n", - " ax.text(x, y, z, str(node), ha='center', va='center')\n", - "\n", - "# Plot edges\n", - "for (u, v) in G.edges():\n", - " x1, y1, z1 = pos_3d[u]\n", - " x2, y2, z2 = pos_3d[v]\n", - " ax.plot([x1, x2], [y1, y2], [z1, z2], 'k-', alpha=0.5)\n", - "\n", - "ax.view_init(elev=0, azim=90) # Rotate the view: elevation=20 degrees, azimuth=45 degrees\n", - "plt.show()\n", - "\n", - "# Also show the 2D projection for reference\n", - "plt.figure(figsize=(6, 6))\n", - "pos_2d = {n: (G.nodes[n]['x'], G.nodes[n]['y']) for n in G.nodes}\n", - "nx.draw(G, pos_2d, with_labels=True, node_color='orange', node_size=200, arrows=True)\n", - "plt.show()" + "compartmentalize(MorphTree.from_nx(G), num_comps=2).plot()" ] }, { From cda2c583fdad0ad94815eedbac843f942efc8f96 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Wed, 28 May 2025 17:23:46 +0200 Subject: [PATCH 14/24] wip: try to get import to work --- dev.ipynb | 1271 ++++++++--------------------------------------------- 1 file changed, 191 insertions(+), 1080 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index 03901afc8..fd14d8358 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 388, + "execution_count": 141, "metadata": {}, "outputs": [], "source": [ @@ -81,11 +81,14 @@ " n_edges = len(self.edge_attrs)\n", "\n", " node_keys = list(next(iter(self.node_attrs.values())).keys())\n", - " edge_keys = list(next(iter(self.edge_attrs.values())).keys())\n", + " if len(self.edge_attrs) > 0:\n", + " edge_keys = list(next(iter(self.edge_attrs.values())).keys())\n", + " else:\n", + " edge_keys = []\n", "\n", " node_attrs = node_keys if len(self.node_attrs) > 0 else []\n", " edge_attrs = edge_keys if len(self.edge_attrs) > 0 else []\n", - " return f\"MorphTree(nodes={n_nodes}*{node_attrs}, edges={n_edges}*{edge_attrs})\"\n", + " return f\"MorphTree(nodes={n_nodes}*{node_attrs}, edges={n_edges}*{edge_attrs}, global={list(self.global_attrs.keys())})\"\n", " \n", " def node(self, i: int) -> Dict[str, Any]:\n", " return self.node_attrs[i]\n", @@ -106,7 +109,7 @@ " edge_attrs = {(i, j): G.edges[i, j] for i, j in G.edges}\n", " return MorphTree(node_attrs, edge_attrs, G.graph)\n", " \n", - " def to_pandas(self, return_global_attrs: bool = False) -> Tuple[pd.DataFrame, pd.DataFrame]:\n", + " def to_pandas(self, return_global_attrs: bool = True) -> Tuple[pd.DataFrame, pd.DataFrame]:\n", " node_df = pd.DataFrame(self.node_attrs.values(), index=self.node_attrs.keys())\n", " edge_df = pd.DataFrame(self.edge_attrs.values(), index=self.edge_attrs.keys())\n", " edge_index = pd.MultiIndex.from_arrays(np.array(self.edges).T)\n", @@ -139,7 +142,7 @@ " for (i, j), attrs in self.edge_attrs.items():\n", " new_edge_attrs[(mapping[i], mapping[j])] = attrs\n", " \n", - " return MorphTree(new_node_attrs, new_edge_attrs)\n", + " return MorphTree(new_node_attrs, new_edge_attrs, self.global_attrs)\n", " \n", " def reorder_tree(self, new_order: np.ndarray) -> MorphTree:\n", " # TODO: check this does what I think it does, i.e. change the edge orientation\n", @@ -309,9 +312,13 @@ "\n", " # collect comps and comp_edges\n", " branch_nodes, branch_edges = [], []\n", + " xyzr = []\n", " for i, branch in enumerate(branches):\n", " node_attrs = nodes_df.loc[branch]\n", - " xyz_i = node_attrs[[\"x\", \"y\", \"z\"]]\n", + " xyzr_i = node_attrs[[\"x\", \"y\", \"z\", \"r\"]]\n", + " xyzr.append(xyzr_i.values)\n", + "\n", + " xyz_i = xyzr_i[[\"x\", \"y\", \"z\"]]\n", " edge_lens = ((xyz_i.diff(axis=0).fillna(0)**2).sum(axis=1)**.5)\n", " # TODO: handle nans\n", " node_attrs[\"l\"] = edge_lens.cumsum() # path length\n", @@ -343,7 +350,7 @@ " # Interpolate xyzr coordinates and combine with attributes\n", " x = jnp.array([0] + comp_locs + [branch_len]) # 0, branch_len = branchpoints\n", " xp = jnp.array(node_attrs[\"l\"].values)\n", - " fp = jnp.array(node_attrs[[\"x\", \"y\", \"z\", \"r\"]].values)\n", + " fp = jnp.array(xyzr_i.values)\n", " #TODO: interpolate r differently!\n", " comp_attrs = np.hstack([comp_attrs, np.array(v_interp(x, xp, fp))])\n", " \n", @@ -355,11 +362,10 @@ " branch_edges.append(list(zip(comp_attrs[:-1, 0], comp_attrs[1:, 0])))\n", " branch_nodes.append(comp_attrs)\n", "\n", - " # TODO: add missing attrs, cell_index, axial_resistvity, membrane_capacitance, voltage\n", " branch_nodes = jnp.concatenate(branch_nodes)\n", - " comp_attrs_keys = [\"idx\", \"branch\", \"branchpoint\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", + " comp_attrs_keys = [\"idx\", \"branch_index\", \"branchpoint\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", - " int_cols = [\"idx\", \"branch\", \"id\"]\n", + " int_cols = [\"idx\", \"branch_index\", \"id\"] # TODO: rename to branch!\n", " bool_cols = [\"branchpoint\"]\n", " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", " comp_df[bool_cols] = comp_df[bool_cols].astype(bool)\n", @@ -372,30 +378,192 @@ " comp_edges = sum(branch_edges, [])\n", " comp_edge_attrs = {(i,j): {\"comp_edge\": True, \"synapse\": False} for i,j in comp_edges}\n", "\n", - " comp_tree = MorphTree(comp_attrs, comp_edge_attrs)\n", + " global_attrs = {\"xyzr\": xyzr} # TODO: rm xyzr from Module? only used for plotting\n", + " comp_tree = MorphTree(comp_attrs, comp_edge_attrs, global_attrs)\n", " comp_tree = comp_tree.reindex_nodes(dict(zip(comp_df.index, range(len(comp_df)))))\n", " return comp_tree\n", "\n", "def _add_meta_data(tree: MorphTree) -> MorphTree:\n", - " global_attrs = {\"channels\": {}, \"synapses\": {}, \"xyzr\": None} # TODO: add xyzr\n", - "\n", " group_ids = {0: \"undefined\", 1: \"soma\", 2: \"axon\", 3: \"basal\", 4: \"apical\"}\n", " fill_w = lambda x: np.full(len(tree.nodes), x)\n", "\n", - " nodes_df, edge_df = tree.to_pandas()\n", - " nodes_df[\"cell\"] = fill_w(0)\n", - " nodes_df[\"comp\"] = np.arange(len(nodes_df))\n", + " nodes_df, edge_df, global_attrs = tree.to_pandas()\n", + " global_attrs = pd.concat([global_attrs, pd.Series({\"channels\": {}, \"synapses\": {}})])\n", + " \n", + " nodes_df[\"cell_index\"] = fill_w(0) # rename to cell\n", + " nodes_df[\"comp_index\"] = np.arange(len(nodes_df)) # rename to comp\n", " nodes_df[\"id\"] = nodes_df[\"id\"].apply(lambda x: [group_ids[x]])\n", " nodes_df = nodes_df.rename(columns={\"r\": \"radius\", \"l\": \"length\", \"id\": \"groups\"})\n", " nodes_df[\"capacitance\"] = fill_w(1.0)\n", " nodes_df[\"v\"] = fill_w(-70.0)\n", " nodes_df[\"axial_resistivity\"] = fill_w(1000.0)\n", "\n", - " return MorphTree.from_pandas(nodes_df, edge_df, pd.Series(global_attrs))\n", + " return MorphTree.from_pandas(nodes_df, edge_df, global_attrs)\n", "\n", - "# def set_solve_order(tree: MorphTree, solve_order: List[int]) -> MorphTree:\n", - "# # TODO: do we want to rm branchpoints and comp_edges?\n", - "# return" + "def _remove_branchpoints(tree: MorphTree) -> MorphTree:\n", + " G = tree.to_nx()\n", + " branchpoints = [n for n in G.nodes if G.nodes[n][\"branchpoint\"]]\n", + " for n in branchpoints:\n", + " parent = next(G.predecessors(n))\n", + " children = list(G.successors(n))\n", + " \n", + " # remove branchpoint and connect parent to children\n", + " G.remove_node(n)\n", + " G.add_edges_from([(parent, c) for c in children], comp_edge=True, synapse=False)\n", + " \n", + " tree = MorphTree.from_nx(G)\n", + " for n in tree.node_attrs:\n", + " tree.node_attrs[n].pop(\"branchpoint\")\n", + " # TODO: relabel comps?\n", + " return tree" + ] + }, + { + "cell_type": "code", + "execution_count": 142, + "metadata": {}, + "outputs": [], + "source": [ + "from jaxley.io.graph import _build_module_scaffold\n", + "\n", + "def _build_module(\n", + " solve_graph: nx.DiGraph,\n", + " assign_groups: bool = True,\n", + "):\n", + " # nodes and edges\n", + " node_df = pd.DataFrame(\n", + " [d for i, d in solve_graph.nodes(data=True)], index=solve_graph.nodes\n", + " ).sort_index()\n", + "\n", + " edge_type = nx.get_edge_attributes(solve_graph, \"type\")\n", + " synapse_edges = pd.DataFrame(\n", + " [\n", + " {\n", + " \"pre_index\": i,\n", + " \"post_index\": j,\n", + " **solve_graph.edges[i, j],\n", + " }\n", + " for (i, j), t in edge_type.items()\n", + " if t == \"synapse\"\n", + " ]\n", + " )\n", + "\n", + " # branches\n", + " branch_of_node = lambda i: solve_graph.nodes[i][\"branch_index\"]\n", + " branch_edges_df = pd.DataFrame(\n", + " [\n", + " (branch_of_node(i), branch_of_node(j))\n", + " for (i, j), t in edge_type.items()\n", + " if t == \"inter_branch\"\n", + " ],\n", + " columns=[\"parent_branch_index\", \"child_branch_index\"],\n", + " )\n", + "\n", + " # drop special attrs from nodes and ignore error if col does not exist\n", + " # x,y,z can be re-computed from xyzr if needed\n", + " optional_attrs = [\n", + " \"recordings\",\n", + " \"externals\",\n", + " \"external_inds\",\n", + " \"trainable\",\n", + " ]\n", + " node_df = node_df.drop(columns=optional_attrs, errors=\"ignore\")\n", + "\n", + " # synapses\n", + " synapse_edges = synapse_edges.drop([\"l\", \"type\"], axis=1, errors=\"ignore\")\n", + " synapse_edges = synapse_edges.rename({\"syn_type\": \"type\"}, axis=1)\n", + " synapse_edges.rename({\"edge_index\": \"global_edge_index\"}, axis=1, inplace=True)\n", + "\n", + " # build module\n", + " acc_parents = []\n", + " parent_branch_inds = branch_edges_df.set_index(\"child_branch_index\").sort_index()[\n", + " \"parent_branch_index\"\n", + " ]\n", + " assert np.std(node_df.groupby(\"branch_index\").size().to_numpy()) < 1e-8, (\n", + " \"`from_graph()` does not support a varying number of compartments in each \"\n", + " \"branch.\"\n", + " )\n", + " for branch_inds in node_df.groupby(\"cell_index\")[\"branch_index\"].unique():\n", + " root_branch_idx = branch_inds[0]\n", + " parents = parent_branch_inds.loc[branch_inds[1:]] - root_branch_idx\n", + " acc_parents.append([-1] + parents.tolist())\n", + "\n", + " # TODO: support inhom ncomps\n", + " module = _build_module_scaffold(\n", + " node_df, solve_graph.graph[\"type\"], acc_parents, solve_graph.graph[\"xyzr\"]\n", + " )\n", + "\n", + " # set global attributes of module. `xyzr` is passed here again, although it has\n", + " # already been passed to `_build_module_scaffold`. `jx.Cell` requires xyzr at\n", + " # __init__()`, all other modules do not.\n", + " for k, v in solve_graph.graph.items():\n", + " if k not in [\"type\"]:\n", + " setattr(module, k, v)\n", + "\n", + " if assign_groups and \"groups\" in node_df.columns:\n", + " groups = node_df.pop(\"groups\").explode()\n", + " groups = (\n", + " pd.DataFrame(groups)\n", + " .groupby(\"groups\")\n", + " .apply(lambda x: x.index.values, include_groups=False)\n", + " .to_dict()\n", + " )\n", + " for group_name, group_inds in groups.items():\n", + " module.select(nodes=group_inds).add_to_group(group_name)\n", + "\n", + " node_df.columns = [\n", + " \"global_\" + col if \"local\" not in col and \"index\" in col else col\n", + " for col in node_df.columns\n", + " ]\n", + " # set column-wise. preserves cols not in df.\n", + " module.nodes[node_df.columns] = node_df\n", + " module.edges = synapse_edges if not synapse_edges.empty else module.edges\n", + "\n", + " # add all the extra attrs\n", + " module.membrane_current_names = [c.current_name for c in module.channels]\n", + " module.synapse_names = [s._name for s in module.synapses]\n", + "\n", + " return module" + ] + }, + { + "cell_type": "code", + "execution_count": 143, + "metadata": {}, + "outputs": [], + "source": [ + "morph_tree = swc_to_morph_tree(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", + "morph_comps = compartmentalize(morph_tree, num_comps=1)\n", + "morph_comps = _add_meta_data(morph_comps)\n", + "morph_comps = _remove_branchpoints(morph_comps)" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "metadata": {}, + "outputs": [ + { + "ename": "KeyError", + "evalue": "\"None of [Index([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,\\n ...\\n 145, 146, 147, 148, 149, 150, 151, 152, 153, 154],\\n dtype='int64', name='child_branch_index', length=154)] are in the [index]\"", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[144], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43m_build_module\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmorph_comps\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mto_nx\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n", + "Cell \u001b[0;32mIn[142], line 62\u001b[0m, in \u001b[0;36m_build_module\u001b[0;34m(solve_graph, assign_groups)\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m branch_inds \u001b[38;5;129;01min\u001b[39;00m node_df\u001b[38;5;241m.\u001b[39mgroupby(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcell_index\u001b[39m\u001b[38;5;124m\"\u001b[39m)[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbranch_index\u001b[39m\u001b[38;5;124m\"\u001b[39m]\u001b[38;5;241m.\u001b[39munique():\n\u001b[1;32m 61\u001b[0m root_branch_idx \u001b[38;5;241m=\u001b[39m branch_inds[\u001b[38;5;241m0\u001b[39m]\n\u001b[0;32m---> 62\u001b[0m parents \u001b[38;5;241m=\u001b[39m \u001b[43mparent_branch_inds\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mloc\u001b[49m\u001b[43m[\u001b[49m\u001b[43mbranch_inds\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m]\u001b[49m\u001b[43m]\u001b[49m \u001b[38;5;241m-\u001b[39m root_branch_idx\n\u001b[1;32m 63\u001b[0m acc_parents\u001b[38;5;241m.\u001b[39mappend([\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m] \u001b[38;5;241m+\u001b[39m parents\u001b[38;5;241m.\u001b[39mtolist())\n\u001b[1;32m 65\u001b[0m \u001b[38;5;66;03m# TODO: support inhom ncomps\u001b[39;00m\n", + "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexing.py:1191\u001b[0m, in \u001b[0;36m_LocationIndexer.__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 1189\u001b[0m maybe_callable \u001b[38;5;241m=\u001b[39m com\u001b[38;5;241m.\u001b[39mapply_if_callable(key, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj)\n\u001b[1;32m 1190\u001b[0m maybe_callable \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_check_deprecated_callable_usage(key, maybe_callable)\n\u001b[0;32m-> 1191\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_getitem_axis\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmaybe_callable\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexing.py:1420\u001b[0m, in \u001b[0;36m_LocIndexer._getitem_axis\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1417\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(key, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mndim\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;129;01mand\u001b[39;00m key\u001b[38;5;241m.\u001b[39mndim \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m 1418\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCannot index with multidimensional key\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m-> 1420\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_getitem_iterable\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1422\u001b[0m \u001b[38;5;66;03m# nested tuple slicing\u001b[39;00m\n\u001b[1;32m 1423\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_nested_tuple(key, labels):\n", + "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexing.py:1360\u001b[0m, in \u001b[0;36m_LocIndexer._getitem_iterable\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1357\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_validate_key(key, axis)\n\u001b[1;32m 1359\u001b[0m \u001b[38;5;66;03m# A collection of keys\u001b[39;00m\n\u001b[0;32m-> 1360\u001b[0m keyarr, indexer \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_listlike_indexer\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1361\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39m_reindex_with_indexers(\n\u001b[1;32m 1362\u001b[0m {axis: [keyarr, indexer]}, copy\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m, allow_dups\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 1363\u001b[0m )\n", + "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexing.py:1558\u001b[0m, in \u001b[0;36m_LocIndexer._get_listlike_indexer\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1555\u001b[0m ax \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39m_get_axis(axis)\n\u001b[1;32m 1556\u001b[0m axis_name \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39m_get_axis_name(axis)\n\u001b[0;32m-> 1558\u001b[0m keyarr, indexer \u001b[38;5;241m=\u001b[39m \u001b[43max\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_indexer_strict\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis_name\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1560\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m keyarr, indexer\n", + "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexes/base.py:6200\u001b[0m, in \u001b[0;36mIndex._get_indexer_strict\u001b[0;34m(self, key, axis_name)\u001b[0m\n\u001b[1;32m 6197\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 6198\u001b[0m keyarr, indexer, new_indexer \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_reindex_non_unique(keyarr)\n\u001b[0;32m-> 6200\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_raise_if_missing\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkeyarr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mindexer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis_name\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 6202\u001b[0m keyarr \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtake(indexer)\n\u001b[1;32m 6203\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(key, Index):\n\u001b[1;32m 6204\u001b[0m \u001b[38;5;66;03m# GH 42790 - Preserve name from an Index\u001b[39;00m\n", + "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexes/base.py:6249\u001b[0m, in \u001b[0;36mIndex._raise_if_missing\u001b[0;34m(self, key, indexer, axis_name)\u001b[0m\n\u001b[1;32m 6247\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m nmissing:\n\u001b[1;32m 6248\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m nmissing \u001b[38;5;241m==\u001b[39m \u001b[38;5;28mlen\u001b[39m(indexer):\n\u001b[0;32m-> 6249\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNone of [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mkey\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m] are in the [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00maxis_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m]\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 6251\u001b[0m not_found \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(ensure_index(key)[missing_mask\u001b[38;5;241m.\u001b[39mnonzero()[\u001b[38;5;241m0\u001b[39m]]\u001b[38;5;241m.\u001b[39munique())\n\u001b[1;32m 6252\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnot_found\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m not in index\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[0;31mKeyError\u001b[0m: \"None of [Index([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,\\n ...\\n 145, 146, 147, 148, 149, 150, 151, 152, 153, 154],\\n dtype='int64', name='child_branch_index', length=154)] are in the [index]\"" + ] + } + ], + "source": [ + "_build_module(morph_comps.to_nx())" ] }, { @@ -560,1063 +728,6 @@ " " ] }, - { - "cell_type": "code", - "execution_count": 239, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "([1000.0,\n", - " 0,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 0,\n", - " 0.0,\n", - " 0.0,\n", - " 1.0,\n", - " 1.0,\n", - " 'apical',\n", - " 0.5,\n", - " 0.5,\n", - " 99.99,\n", - " 0.5,\n", - " 0.5,\n", - " Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", - " Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", - " 0.24,\n", - " -70.0,\n", - " -38.814059082992166,\n", - " -467.2217575574461,\n", - " 61.146926321832275,\n", - " 1000.0,\n", - " 0,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 1,\n", - " nan,\n", - " nan,\n", - " nan,\n", - " nan,\n", - " 'apical',\n", - " nan,\n", - " nan,\n", - " 0.0,\n", - " nan,\n", - " nan,\n", - " nan,\n", - " nan,\n", - " 0.4,\n", - " -70.0,\n", - " -35.24,\n", - " -400.77,\n", - " 11.68,\n", - " 1000.0,\n", - " 1,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 2,\n", - " 0.0,\n", - " 0.0,\n", - " 1.0,\n", - " 1.0,\n", - " 'apical',\n", - " 0.5,\n", - " 0.5,\n", - " 4.273938446576365,\n", - " 0.5,\n", - " 0.5,\n", - " Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", - " Array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],\n", - " [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float64),\n", - " 0.4,\n", - " -70.0,\n", - " -34.76658953359951,\n", - " -399.8027942229742,\n", - " 12.197484358005454,\n", - " 1000.0,\n", - " 1,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 3,\n", - " 'apical',\n", - " 0.0,\n", - " 0.4,\n", - " -70.0,\n", - " -33.9,\n", - " -397.85,\n", - " 12.15,\n", - " 1000.0,\n", - " 2,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 4,\n", - " 'apical',\n", - " 240.98216917972093,\n", - " 0.24,\n", - " -70.0,\n", - " -46.28514596269051,\n", - " -486.53457919707705,\n", - " 27.28,\n", - " 1000.0,\n", - " 3,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 5,\n", - " 'apical',\n", - " 46.75130571468936,\n", - " 0.4,\n", - " -70.0,\n", - " -28.605582752668862,\n", - " -387.37532948963417,\n", - " 25.76,\n", - " 1000.0,\n", - " 3,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 6,\n", - " 'apical',\n", - " 0.0,\n", - " 0.4,\n", - " -70.0,\n", - " -22.09,\n", - " -372.8,\n", - " 9.43,\n", - " 1000.0,\n", - " 4,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 7,\n", - " 'apical',\n", - " 86.53353014513984,\n", - " 0.24,\n", - " -70.0,\n", - " -60.46649412843316,\n", - " -414.1453724961543,\n", - " 11.51407401462471,\n", - " 1000.0,\n", - " 5,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 8,\n", - " 'apical',\n", - " 17.102847471669104,\n", - " 0.4,\n", - " -70.0,\n", - " -22.214137277739816,\n", - " -372.96551637031973,\n", - " 17.978920527015447,\n", - " 1000.0,\n", - " 5,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 9,\n", - " 'apical',\n", - " 0.0,\n", - " 0.4,\n", - " -70.0,\n", - " -19.99,\n", - " -367.96,\n", - " 15.84,\n", - " 1000.0,\n", - " 6,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 10,\n", - " 'apical',\n", - " 24.60469133685882,\n", - " 0.24,\n", - " -70.0,\n", - " -21.764906476169717,\n", - " -377.3156131006652,\n", - " 13.974884579197457,\n", - " 1000.0,\n", - " 6,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 11,\n", - " 'apical',\n", - " 0.0,\n", - " 0.24,\n", - " -70.0,\n", - " -19.63,\n", - " -387.74,\n", - " 15.52,\n", - " 1000.0,\n", - " 7,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 12,\n", - " 'apical',\n", - " 50.052056161692775,\n", - " 0.4,\n", - " -70.0,\n", - " -14.667438419442123,\n", - " -353.9810998217457,\n", - " 9.64331860144327,\n", - " 1000.0,\n", - " 7,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 13,\n", - " 'apical',\n", - " 0.0,\n", - " 0.55,\n", - " -70.0,\n", - " -12.52,\n", - " -343.56,\n", - " -2.16,\n", - " 1000.0,\n", - " 8,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 14,\n", - " 'apical',\n", - " 53.76132118557308,\n", - " 0.24,\n", - " -70.0,\n", - " -26.59348381607843,\n", - " -376.98191136107283,\n", - " -4.4,\n", - " 1000.0,\n", - " 9,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 15,\n", - " 'apical',\n", - " 159.71442568142288,\n", - " 0.5782846917122577,\n", - " -70.0,\n", - " -7.645618289361691,\n", - " -303.3455260496049,\n", - " 5.27622108401229,\n", - " 1000.0,\n", - " 9,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 16,\n", - " 'apical',\n", - " 0.0,\n", - " 0.71,\n", - " -70.0,\n", - " -4.13,\n", - " -268.18,\n", - " -5.589999999999999,\n", - " 1000.0,\n", - " 10,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 17,\n", - " 'apical',\n", - " 74.89970414900556,\n", - " 0.24,\n", - " -70.0,\n", - " -5.55926797785782,\n", - " -358.39305045595876,\n", - " -4.675272523401764,\n", - " 1000.0,\n", - " 10,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 18,\n", - " 'apical',\n", - " 0.0,\n", - " 0.24,\n", - " -70.0,\n", - " 12.91,\n", - " -382.04,\n", - " 5.110000000000001,\n", - " 1000.0,\n", - " 11,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 19,\n", - " 'apical',\n", - " 18.602360065325048,\n", - " 0.79,\n", - " -70.0,\n", - " -2.195,\n", - " -261.665,\n", - " 0.7599999999999998,\n", - " 1000.0,\n", - " 11,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 20,\n", - " 'apical',\n", - " 0.0,\n", - " 0.87,\n", - " -70.0,\n", - " -0.2599999999999998,\n", - " -255.15,\n", - " 7.109999999999999,\n", - " 1000.0,\n", - " 12,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 21,\n", - " 'apical',\n", - " 117.73329521015768,\n", - " 0.4,\n", - " -70.0,\n", - " -16.252533797319938,\n", - " -285.3936257314047,\n", - " 28.87,\n", - " 1000.0,\n", - " 13,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 22,\n", - " 'apical',\n", - " 3.485670667174398,\n", - " 0.87,\n", - " -70.0,\n", - " -0.044999999999999984,\n", - " -254.215,\n", - " 8.565,\n", - " 1000.0,\n", - " 13,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 23,\n", - " 'apical',\n", - " 0.0,\n", - " 0.87,\n", - " -70.0,\n", - " 0.17000000000000004,\n", - " -253.28,\n", - " 10.02,\n", - " 1000.0,\n", - " 14,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 24,\n", - " 'apical',\n", - " 69.90591435690905,\n", - " 0.24,\n", - " -70.0,\n", - " -8.907514028562915,\n", - " -266.4040510787294,\n", - " -11.251953956792763,\n", - " 1000.0,\n", - " 15,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 25,\n", - " 'apical',\n", - " 4.189092980586614,\n", - " 0.87,\n", - " -70.0,\n", - " 0.43499999999999994,\n", - " -252.16,\n", - " 11.77,\n", - " 1000.0,\n", - " 15,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 26,\n", - " 'apical',\n", - " 0.0,\n", - " 0.87,\n", - " -70.0,\n", - " 0.7,\n", - " -251.04,\n", - " 13.52,\n", - " 1000.0,\n", - " 16,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 27,\n", - " 'apical',\n", - " 113.68283329856779,\n", - " 0.24,\n", - " -70.0,\n", - " 7.776276453831945,\n", - " -281.71696585754637,\n", - " 34.33086009293123,\n", - " 1000.0,\n", - " 17,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 28,\n", - " 'apical',\n", - " 16.344032441943455,\n", - " 0.87,\n", - " -70.0,\n", - " -0.7360595221854835,\n", - " -244.8574840051365,\n", - " 8.372565868529955,\n", - " 1000.0,\n", - " 17,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 29,\n", - " 'apical',\n", - " 0.0,\n", - " 0.87,\n", - " -70.0,\n", - " -0.75,\n", - " -236.83,\n", - " 8.0,\n", - " 1000.0,\n", - " 18,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 30,\n", - " 'apical',\n", - " 83.6221267068054,\n", - " 0.24,\n", - " -70.0,\n", - " -16.58416113415944,\n", - " -260.2859901965372,\n", - " 43.27,\n", - " 1000.0,\n", - " 19,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 31,\n", - " 'apical',\n", - " 71.4833481477609,\n", - " 0.87,\n", - " -70.0,\n", - " 0.8145650574449815,\n", - " -214.8727592817948,\n", - " -2.2375183407402344,\n", - " 1000.0,\n", - " 19,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 32,\n", - " 'apical',\n", - " 0.0,\n", - " 1.03,\n", - " -70.0,\n", - " 6.38,\n", - " -184.71,\n", - " 0.9500000000000002,\n", - " 1000.0,\n", - " 20,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 33,\n", - " 'apical',\n", - " 56.00782300459446,\n", - " 0.4,\n", - " -70.0,\n", - " 21.32859606702451,\n", - " -232.50102170552017,\n", - " 15.070872611429797,\n", - " 1000.0,\n", - " 20,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 34,\n", - " 'apical',\n", - " 0.0,\n", - " 0.24,\n", - " -70.0,\n", - " 36.63,\n", - " -227.87,\n", - " 25.52,\n", - " 1000.0,\n", - " 21,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 35,\n", - " 'apical',\n", - " 8.651398442038415,\n", - " 1.1021193311462694,\n", - " -70.0,\n", - " 6.894451228843388,\n", - " -183.5945543449377,\n", - " 4.442708639932774,\n", - " 1000.0,\n", - " 21,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 36,\n", - " 'apical',\n", - " 0.0,\n", - " 1.18,\n", - " -70.0,\n", - " 7.45,\n", - " -182.39,\n", - " 8.56,\n", - " 1000.0,\n", - " 22,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 37,\n", - " 'apical',\n", - " 11.943457742966501,\n", - " 0.7297356833485694,\n", - " -70.0,\n", - " 4.052951545951412,\n", - " -184.0594273139219,\n", - " 6.411057259097895,\n", - " 1000.0,\n", - " 22,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 38,\n", - " 'apical',\n", - " 0.0,\n", - " 0.4,\n", - " -70.0,\n", - " 0.97,\n", - " -185.37,\n", - " 9.68,\n", - " 1000.0,\n", - " 23,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 39,\n", - " 'apical',\n", - " 11.834162412270667,\n", - " 1.18,\n", - " -70.0,\n", - " 7.385,\n", - " -181.41,\n", - " 14.395,\n", - " 1000.0,\n", - " 23,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 40,\n", - " 'apical',\n", - " 0.0,\n", - " 1.18,\n", - " -70.0,\n", - " 7.32,\n", - " -180.43,\n", - " 20.23,\n", - " 1000.0,\n", - " 24,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 41,\n", - " 'apical',\n", - " 60.482116932522686,\n", - " 0.4,\n", - " -70.0,\n", - " 16.78281904208192,\n", - " -194.19403766018746,\n", - " 29.763430972274353,\n", - " 1000.0,\n", - " 24,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 42,\n", - " 'apical',\n", - " 0.0,\n", - " 0.4,\n", - " -70.0,\n", - " 20.23,\n", - " -213.61,\n", - " 44.88,\n", - " 1000.0,\n", - " 25,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 43,\n", - " 'apical',\n", - " 2.2265219513851697,\n", - " 1.18,\n", - " -70.0,\n", - " 7.71,\n", - " -179.465,\n", - " 19.835,\n", - " 1000.0,\n", - " 25,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 44,\n", - " 'apical',\n", - " 0.0,\n", - " 1.18,\n", - " -70.0,\n", - " 8.1,\n", - " -178.5,\n", - " 19.44,\n", - " 1000.0,\n", - " 26,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 45,\n", - " 'apical',\n", - " 86.49836641101749,\n", - " 0.4,\n", - " -70.0,\n", - " 2.0134462481703657,\n", - " -192.55559886544083,\n", - " 30.605679248252855,\n", - " 1000.0,\n", - " 27,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 46,\n", - " 'apical',\n", - " 101.86565020617884,\n", - " 1.03,\n", - " -70.0,\n", - " 10.814626291741611,\n", - " -152.1248271646496,\n", - " 5.060345670700826,\n", - " 1000.0,\n", - " 27,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 47,\n", - " 'apical',\n", - " 0.0,\n", - " 1.34,\n", - " -70.0,\n", - " 12.31,\n", - " -122.33,\n", - " 5.84,\n", - " 1000.0,\n", - " 28,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 48,\n", - " 'apical',\n", - " 104.99517531503017,\n", - " 0.4,\n", - " -70.0,\n", - " 2.5229464777183814,\n", - " -159.7176697734082,\n", - " 35.99978727480884,\n", - " 1000.0,\n", - " 29,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 49,\n", - " 'soma',\n", - " 181.9201970835877,\n", - " 1.5,\n", - " -70.0,\n", - " 17.78697106422322,\n", - " -77.08047502970176,\n", - " 1.84,\n", - " 1000.0,\n", - " 29,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 50,\n", - " 'soma',\n", - " 0.0,\n", - " 2.6,\n", - " -70.0,\n", - " 4.06,\n", - " -11.45,\n", - " 0.0,\n", - " 1000.0,\n", - " 30,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 51,\n", - " 'apical',\n", - " 114.30351708313648,\n", - " 0.4688830535120067,\n", - " -70.0,\n", - " 25.35863421828102,\n", - " -135.4016477545103,\n", - " 44.08334802741253,\n", - " 1000.0,\n", - " 30,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 52,\n", - " 'apical',\n", - " 0.0,\n", - " 0.4,\n", - " -70.0,\n", - " 39.35,\n", - " -173.54,\n", - " 37.91,\n", - " 1000.0,\n", - " 31,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 53,\n", - " 'soma',\n", - " 12.483114327343436,\n", - " 6.360392267553557,\n", - " -70.0,\n", - " 1.9689989528610923,\n", - " -5.833291824125783,\n", - " 0.0,\n", - " 1000.0,\n", - " 31,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 54,\n", - " 'soma',\n", - " 0.0,\n", - " 8.119,\n", - " -70.0,\n", - " 0.0,\n", - " 0.0,\n", - " 0.0,\n", - " 1000.0,\n", - " 32,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 55,\n", - " 'soma',\n", - " 8.321000028787864,\n", - " 7.96,\n", - " -70.0,\n", - " -1.431913946300191,\n", - " 3.8861559375019596,\n", - " 0.0,\n", - " 1000.0,\n", - " 32,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 56,\n", - " 'soma',\n", - " 0.0,\n", - " 7.8,\n", - " -70.0,\n", - " -2.45,\n", - " 7.92,\n", - " 0.0,\n", - " 1000.0,\n", - " 33,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 57,\n", - " 'basal',\n", - " 58.4467372401343,\n", - " 0.71,\n", - " -70.0,\n", - " 10.779450509449843,\n", - " 7.087492384157699,\n", - " 17.28816403482587,\n", - " 1000.0,\n", - " 33,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 58,\n", - " 'basal',\n", - " 0.0,\n", - " 0.71,\n", - " -70.0,\n", - " 12.76,\n", - " 10.56,\n", - " 45.91,\n", - " 1000.0,\n", - " 34,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 59,\n", - " 'basal',\n", - " 60.35739302082753,\n", - " 1.1033645885509442,\n", - " -70.0,\n", - " -3.3812434965374667,\n", - " 8.86799569861848,\n", - " 30.105248620163,\n", - " 1000.0,\n", - " 34,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 60,\n", - " 'basal',\n", - " 0.0,\n", - " 0.71,\n", - " -70.0,\n", - " -12.15,\n", - " 12.01,\n", - " 54.88,\n", - " 1000.0,\n", - " 35,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 61,\n", - " 'basal',\n", - " 7.079516370872465,\n", - " 1.1854499190831111,\n", - " -70.0,\n", - " -11.078350976034892,\n", - " 12.047734120562152,\n", - " 58.25343037825636,\n", - " 1000.0,\n", - " 35,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 62,\n", - " 'basal',\n", - " 0.0,\n", - " 1.34,\n", - " -70.0,\n", - " -12.64,\n", - " 12.85,\n", - " 59.35,\n", - " 1000.0,\n", - " 36,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 63,\n", - " 'basal',\n", - " 7.970702603911401,\n", - " 0.79,\n", - " -70.0,\n", - " -13.57,\n", - " 13.225,\n", - " 51.36,\n", - " 1000.0,\n", - " 36,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 64,\n", - " 'basal',\n", - " 0.0,\n", - " 0.87,\n", - " -70.0,\n", - " -14.99,\n", - " 14.44,\n", - " 47.84,\n", - " 1000.0,\n", - " 37,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 65,\n", - " 'basal',\n", - " 65.42028120792062,\n", - " 0.55,\n", - " -70.0,\n", - " -21.744532926599987,\n", - " 12.614333841750017,\n", - " 48.43476897112083,\n", - " 1000.0,\n", - " 38,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 66,\n", - " 'basal',\n", - " 39.89804629510217,\n", - " 0.55,\n", - " -70.0,\n", - " -20.46462568500629,\n", - " 25.350645679037065,\n", - " 56.67776161924187,\n", - " 1000.0,\n", - " 38,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 67,\n", - " 'basal',\n", - " 0.0,\n", - " 0.55,\n", - " -70.0,\n", - " -24.81,\n", - " 41.27,\n", - " 53.2,\n", - " 1000.0,\n", - " 39,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 68,\n", - " 'basal',\n", - " 47.38843289953645,\n", - " 0.55,\n", - " -70.0,\n", - " -24.06011764647134,\n", - " 58.31648265295836,\n", - " 62.79,\n", - " 1000.0,\n", - " 40,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 69,\n", - " 'basal',\n", - " 11.12056895488611,\n", - " 0.55,\n", - " -70.0,\n", - " -27.373304357762073,\n", - " 45.933339226388014,\n", - " 53.240660871552414,\n", - " 1000.0,\n", - " 40,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 70,\n", - " 'basal',\n", - " 0.0,\n", - " 0.55,\n", - " -70.0,\n", - " -30.14,\n", - " 50.55,\n", - " 53.27,\n", - " 1000.0,\n", - " 41,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 71,\n", - " 'basal',\n", - " 15.819923328277275,\n", - " 0.55,\n", - " -70.0,\n", - " -31.761671906152685,\n", - " 51.63111460410179,\n", - " 60.936085374539985,\n", - " 1000.0,\n", - " 41,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 72,\n", - " 'basal',\n", - " 0.0,\n", - " 0.55,\n", - " -70.0,\n", - " -36.42,\n", - " 55.55,\n", - " 62.63,\n", - " 1000.0,\n", - " 42,\n", - " False,\n", - " 1.0,\n", - " 0,\n", - " 73,\n", - " 'basal',\n", - " 10.67453174716901,\n", - " 0.55,\n", - " -70.0,\n", - " -31.228660429037276,\n", - " 53.8782966236737,\n", - " 55.97186958848435,\n", - " 1000.0,\n", - " 42,\n", - " True,\n", - " 1.0,\n", - " 0,\n", - " 74,\n", - " 'basal',\n", - " 0.0,\n", - " ...],\n", - " PyTreeDef(CustomNode(MorphTree[()], [{0: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'e_test1': *, 'e_test2': *, 'gbar_test1': *, 'gbar_test2': *, 'groups': [*], 'h_test1': *, 'h_test2': *, 'length': *, 'm_test1': *, 'm_test2': *, 'nn_weights_test1': *, 'nn_weights_test2': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 1: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'e_test1': *, 'e_test2': *, 'gbar_test1': *, 'gbar_test2': *, 'groups': [*], 'h_test1': *, 'h_test2': *, 'length': *, 'm_test1': *, 'm_test2': *, 'nn_weights_test1': *, 'nn_weights_test2': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 2: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'e_test1': *, 'e_test2': *, 'gbar_test1': *, 'gbar_test2': *, 'groups': [*], 'h_test1': *, 'h_test2': *, 'length': *, 'm_test1': *, 'm_test2': *, 'nn_weights_test1': *, 'nn_weights_test2': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 3: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 4: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 5: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 6: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 7: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 8: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 9: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 10: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 11: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 12: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 13: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 14: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 15: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 16: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 17: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 18: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 19: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 20: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 21: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 22: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 23: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 24: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 25: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 26: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 27: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 28: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 29: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 30: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 31: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 32: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 33: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 34: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 35: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 36: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 37: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 38: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 39: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 40: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 41: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 42: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 43: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 44: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 45: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 46: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 47: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 48: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 49: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 50: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 51: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 52: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 53: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 54: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 55: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 56: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 57: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 58: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 59: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 60: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 61: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 62: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 63: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 64: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 65: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 66: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 67: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 68: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 69: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 70: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 71: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 72: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 73: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 74: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 75: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 76: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 77: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 78: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 79: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 80: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 81: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 82: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 83: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 84: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 85: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 86: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 87: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 88: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 89: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 90: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 91: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 92: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 93: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 94: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 95: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 96: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 97: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 98: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 99: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 100: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 101: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 102: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 103: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 104: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 105: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 106: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 107: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 108: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 109: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 110: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 111: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 112: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 113: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 114: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 115: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 116: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 117: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 118: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 119: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 120: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 121: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 122: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 123: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 124: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 125: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 126: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 127: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 128: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 129: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 130: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 131: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 132: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 133: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 134: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 135: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 136: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 137: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 138: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 139: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 140: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 141: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 142: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 143: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 144: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 145: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 146: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 147: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 148: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 149: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 150: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 151: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 152: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 153: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 154: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 155: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 156: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 157: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 158: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 159: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 160: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 161: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 162: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 163: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 164: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 165: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 166: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 167: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 168: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 169: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 170: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 171: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 172: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 173: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 174: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 175: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 176: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 177: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 178: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 179: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 180: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 181: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 182: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 183: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 184: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 185: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 186: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 187: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 188: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 189: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 190: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 191: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 192: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 193: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 194: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 195: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 196: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 197: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 198: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 199: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 200: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 201: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 202: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 203: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 204: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 205: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 206: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 207: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 208: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 209: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 210: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 211: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 212: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 213: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 214: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 215: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 216: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 217: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 218: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 219: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 220: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 221: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 222: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 223: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 224: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 225: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 226: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 227: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 228: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 229: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 230: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 231: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}, 232: {'axial_resistivity': *, 'branch': *, 'branchpoint': *, 'capacitance': *, 'cell': *, 'comp': *, 'groups': [*], 'length': *, 'radius': *, 'v': *, 'x': *, 'y': *, 'z': *}}, {(0, 1): {'comp_edge': *, 'e_test2': *, 'gbar_test2': *, 'h_test2': *, 'm_test2': *, 'nn_weights_test2': *, 'synapse': *}, (0, 3): {'comp_edge': *, 'e_test1': *, 'gbar_test1': *, 'h_test1': *, 'm_test1': *, 'nn_weights_test1': *, 'synapse': *}, (1, 2): {'comp_edge': *, 'e_test1': *, 'e_test2': *, 'gbar_test1': *, 'gbar_test2': *, 'h_test1': *, 'h_test2': *, 'm_test1': *, 'm_test2': *, 'nn_weights_test1': *, 'nn_weights_test2': *, 'synapse': *}, (1, 4): {'comp_edge': *, 'synapse': *}, (2, 3): {'comp_edge': *, 'synapse': *}, (3, 5): {'comp_edge': *, 'synapse': *}, (3, 7): {'comp_edge': *, 'synapse': *}, (5, 6): {'comp_edge': *, 'synapse': *}, (6, 8): {'comp_edge': *, 'synapse': *}, (6, 10): {'comp_edge': *, 'synapse': *}, (8, 9): {'comp_edge': *, 'synapse': *}, (9, 12): {'comp_edge': *, 'synapse': *}, (9, 14): {'comp_edge': *, 'synapse': *}, (10, 11): {'comp_edge': *, 'synapse': *}, (11, 231): {'comp_edge': *, 'synapse': *}, (11, 232): {'comp_edge': *, 'synapse': *}, (12, 13): {'comp_edge': *, 'synapse': *}, (13, 15): {'comp_edge': *, 'synapse': *}, (13, 17): {'comp_edge': *, 'synapse': *}, (15, 16): {'comp_edge': *, 'synapse': *}, (16, 19): {'comp_edge': *, 'synapse': *}, (16, 21): {'comp_edge': *, 'synapse': *}, (17, 18): {'comp_edge': *, 'synapse': *}, (18, 226): {'comp_edge': *, 'synapse': *}, (18, 227): {'comp_edge': *, 'synapse': *}, (19, 20): {'comp_edge': *, 'synapse': *}, (20, 22): {'comp_edge': *, 'synapse': *}, (20, 24): {'comp_edge': *, 'synapse': *}, (22, 23): {'comp_edge': *, 'synapse': *}, (23, 25): {'comp_edge': *, 'synapse': *}, (23, 27): {'comp_edge': *, 'synapse': *}, (25, 26): {'comp_edge': *, 'synapse': *}, (26, 28): {'comp_edge': *, 'synapse': *}, (26, 30): {'comp_edge': *, 'synapse': *}, (28, 29): {'comp_edge': *, 'synapse': *}, (29, 31): {'comp_edge': *, 'synapse': *}, (29, 33): {'comp_edge': *, 'synapse': *}, (31, 32): {'comp_edge': *, 'synapse': *}, (32, 35): {'comp_edge': *, 'synapse': *}, (32, 37): {'comp_edge': *, 'synapse': *}, (33, 34): {'comp_edge': *, 'synapse': *}, (34, 224): {'comp_edge': *, 'synapse': *}, (34, 225): {'comp_edge': *, 'synapse': *}, (35, 36): {'comp_edge': *, 'synapse': *}, (36, 39): {'comp_edge': *, 'synapse': *}, (36, 41): {'comp_edge': *, 'synapse': *}, (37, 38): {'comp_edge': *, 'synapse': *}, (38, 216): {'comp_edge': *, 'synapse': *}, (38, 217): {'comp_edge': *, 'synapse': *}, (39, 40): {'comp_edge': *, 'synapse': *}, (40, 43): {'comp_edge': *, 'synapse': *}, (40, 45): {'comp_edge': *, 'synapse': *}, (41, 42): {'comp_edge': *, 'synapse': *}, (42, 208): {'comp_edge': *, 'synapse': *}, (42, 209): {'comp_edge': *, 'synapse': *}, (43, 44): {'comp_edge': *, 'synapse': *}, (44, 46): {'comp_edge': *, 'synapse': *}, (44, 48): {'comp_edge': *, 'synapse': *}, (46, 47): {'comp_edge': *, 'synapse': *}, (47, 49): {'comp_edge': *, 'synapse': *}, (47, 51): {'comp_edge': *, 'synapse': *}, (49, 50): {'comp_edge': *, 'synapse': *}, (50, 53): {'comp_edge': *, 'synapse': *}, (51, 52): {'comp_edge': *, 'synapse': *}, (52, 206): {'comp_edge': *, 'synapse': *}, (52, 207): {'comp_edge': *, 'synapse': *}, (53, 54): {'comp_edge': *, 'synapse': *}, (54, 55): {'comp_edge': *, 'synapse': *}, (54, 57): {'comp_edge': *, 'synapse': *}, (55, 56): {'comp_edge': *, 'synapse': *}, (56, 59): {'comp_edge': *, 'synapse': *}, (57, 58): {'comp_edge': *, 'synapse': *}, (58, 105): {'comp_edge': *, 'synapse': *}, (58, 107): {'comp_edge': *, 'synapse': *}, (59, 60): {'comp_edge': *, 'synapse': *}, (60, 61): {'comp_edge': *, 'synapse': *}, (60, 63): {'comp_edge': *, 'synapse': *}, (61, 62): {'comp_edge': *, 'synapse': *}, (62, 65): {'comp_edge': *, 'synapse': *}, (62, 66): {'comp_edge': *, 'synapse': *}, (63, 64): {'comp_edge': *, 'synapse': *}, (64, 79): {'comp_edge': *, 'synapse': *}, (64, 81): {'comp_edge': *, 'synapse': *}, (66, 67): {'comp_edge': *, 'synapse': *}, (67, 68): {'comp_edge': *, 'synapse': *}, (67, 69): {'comp_edge': *, 'synapse': *}, (69, 70): {'comp_edge': *, 'synapse': *}, (70, 71): {'comp_edge': *, 'synapse': *}, (70, 73): {'comp_edge': *, 'synapse': *}, (71, 72): {'comp_edge': *, 'synapse': *}, (72, 75): {'comp_edge': *, 'synapse': *}, (72, 76): {'comp_edge': *, 'synapse': *}, (73, 74): {'comp_edge': *, 'synapse': *}, (74, 77): {'comp_edge': *, 'synapse': *}, (74, 78): {'comp_edge': *, 'synapse': *}, (79, 80): {'comp_edge': *, 'synapse': *}, (80, 83): {'comp_edge': *, 'synapse': *}, (80, 84): {'comp_edge': *, 'synapse': *}, (81, 82): {'comp_edge': *, 'synapse': *}, (82, 91): {'comp_edge': *, 'synapse': *}, (82, 93): {'comp_edge': *, 'synapse': *}, (84, 85): {'comp_edge': *, 'synapse': *}, (85, 86): {'comp_edge': *, 'synapse': *}, (85, 88): {'comp_edge': *, 'synapse': *}, (86, 87): {'comp_edge': *, 'synapse': *}, (87, 89): {'comp_edge': *, 'synapse': *}, (87, 90): {'comp_edge': *, 'synapse': *}, (91, 92): {'comp_edge': *, 'synapse': *}, (92, 95): {'comp_edge': *, 'synapse': *}, (92, 96): {'comp_edge': *, 'synapse': *}, (93, 94): {'comp_edge': *, 'synapse': *}, (94, 97): {'comp_edge': *, 'synapse': *}, (94, 99): {'comp_edge': *, 'synapse': *}, (97, 98): {'comp_edge': *, 'synapse': *}, (98, 100): {'comp_edge': *, 'synapse': *}, (98, 102): {'comp_edge': *, 'synapse': *}, (100, 101): {'comp_edge': *, 'synapse': *}, (101, 103): {'comp_edge': *, 'synapse': *}, (101, 104): {'comp_edge': *, 'synapse': *}, (105, 106): {'comp_edge': *, 'synapse': *}, (106, 109): {'comp_edge': *, 'synapse': *}, (106, 111): {'comp_edge': *, 'synapse': *}, (107, 108): {'comp_edge': *, 'synapse': *}, (108, 201): {'comp_edge': *, 'synapse': *}, (108, 202): {'comp_edge': *, 'synapse': *}, (109, 110): {'comp_edge': *, 'synapse': *}, (110, 112): {'comp_edge': *, 'synapse': *}, (110, 114): {'comp_edge': *, 'synapse': *}, (112, 113): {'comp_edge': *, 'synapse': *}, (113, 115): {'comp_edge': *, 'synapse': *}, (113, 117): {'comp_edge': *, 'synapse': *}, (115, 116): {'comp_edge': *, 'synapse': *}, (116, 119): {'comp_edge': *, 'synapse': *}, (116, 120): {'comp_edge': *, 'synapse': *}, (117, 118): {'comp_edge': *, 'synapse': *}, (118, 121): {'comp_edge': *, 'synapse': *}, (118, 123): {'comp_edge': *, 'synapse': *}, (121, 122): {'comp_edge': *, 'synapse': *}, (122, 125): {'comp_edge': *, 'synapse': *}, (122, 127): {'comp_edge': *, 'synapse': *}, (123, 124): {'comp_edge': *, 'synapse': *}, (124, 151): {'comp_edge': *, 'synapse': *}, (124, 153): {'comp_edge': *, 'synapse': *}, (125, 126): {'comp_edge': *, 'synapse': *}, (126, 129): {'comp_edge': *, 'synapse': *}, (126, 130): {'comp_edge': *, 'synapse': *}, (127, 128): {'comp_edge': *, 'synapse': *}, (128, 131): {'comp_edge': *, 'synapse': *}, (128, 133): {'comp_edge': *, 'synapse': *}, (131, 132): {'comp_edge': *, 'synapse': *}, (132, 135): {'comp_edge': *, 'synapse': *}, (132, 136): {'comp_edge': *, 'synapse': *}, (133, 134): {'comp_edge': *, 'synapse': *}, (134, 146): {'comp_edge': *, 'synapse': *}, (134, 147): {'comp_edge': *, 'synapse': *}, (136, 137): {'comp_edge': *, 'synapse': *}, (137, 138): {'comp_edge': *, 'synapse': *}, (137, 140): {'comp_edge': *, 'synapse': *}, (138, 139): {'comp_edge': *, 'synapse': *}, (139, 142): {'comp_edge': *, 'synapse': *}, (139, 143): {'comp_edge': *, 'synapse': *}, (140, 141): {'comp_edge': *, 'synapse': *}, (141, 144): {'comp_edge': *, 'synapse': *}, (141, 145): {'comp_edge': *, 'synapse': *}, (147, 148): {'comp_edge': *, 'synapse': *}, (148, 149): {'comp_edge': *, 'synapse': *}, (148, 150): {'comp_edge': *, 'synapse': *}, (151, 152): {'comp_edge': *, 'synapse': *}, (152, 155): {'comp_edge': *, 'synapse': *}, (152, 157): {'comp_edge': *, 'synapse': *}, (153, 154): {'comp_edge': *, 'synapse': *}, (154, 193): {'comp_edge': *, 'synapse': *}, (154, 194): {'comp_edge': *, 'synapse': *}, (155, 156): {'comp_edge': *, 'synapse': *}, (156, 159): {'comp_edge': *, 'synapse': *}, (156, 161): {'comp_edge': *, 'synapse': *}, (157, 158): {'comp_edge': *, 'synapse': *}, (158, 182): {'comp_edge': *, 'synapse': *}, (158, 183): {'comp_edge': *, 'synapse': *}, (159, 160): {'comp_edge': *, 'synapse': *}, (160, 163): {'comp_edge': *, 'synapse': *}, (160, 165): {'comp_edge': *, 'synapse': *}, (161, 162): {'comp_edge': *, 'synapse': *}, (162, 171): {'comp_edge': *, 'synapse': *}, (162, 172): {'comp_edge': *, 'synapse': *}, (163, 164): {'comp_edge': *, 'synapse': *}, (164, 167): {'comp_edge': *, 'synapse': *}, (164, 168): {'comp_edge': *, 'synapse': *}, (165, 166): {'comp_edge': *, 'synapse': *}, (166, 169): {'comp_edge': *, 'synapse': *}, (166, 170): {'comp_edge': *, 'synapse': *}, (172, 173): {'comp_edge': *, 'synapse': *}, (173, 174): {'comp_edge': *, 'synapse': *}, (173, 176): {'comp_edge': *, 'synapse': *}, (174, 175): {'comp_edge': *, 'synapse': *}, (175, 177): {'comp_edge': *, 'synapse': *}, (175, 178): {'comp_edge': *, 'synapse': *}, (178, 179): {'comp_edge': *, 'synapse': *}, (179, 180): {'comp_edge': *, 'synapse': *}, (179, 181): {'comp_edge': *, 'synapse': *}, (183, 184): {'comp_edge': *, 'synapse': *}, (184, 185): {'comp_edge': *, 'synapse': *}, (184, 187): {'comp_edge': *, 'synapse': *}, (185, 186): {'comp_edge': *, 'synapse': *}, (186, 189): {'comp_edge': *, 'synapse': *}, (186, 190): {'comp_edge': *, 'synapse': *}, (187, 188): {'comp_edge': *, 'synapse': *}, (188, 191): {'comp_edge': *, 'synapse': *}, (188, 192): {'comp_edge': *, 'synapse': *}, (194, 195): {'comp_edge': *, 'synapse': *}, (195, 196): {'comp_edge': *, 'synapse': *}, (195, 197): {'comp_edge': *, 'synapse': *}, (197, 198): {'comp_edge': *, 'synapse': *}, (198, 199): {'comp_edge': *, 'synapse': *}, (198, 200): {'comp_edge': *, 'synapse': *}, (202, 203): {'comp_edge': *, 'synapse': *}, (203, 204): {'comp_edge': *, 'synapse': *}, (203, 205): {'comp_edge': *, 'synapse': *}, (209, 210): {'comp_edge': *, 'synapse': *}, (210, 211): {'comp_edge': *, 'synapse': *}, (210, 212): {'comp_edge': *, 'synapse': *}, (212, 213): {'comp_edge': *, 'synapse': *}, (213, 214): {'comp_edge': *, 'synapse': *}, (213, 215): {'comp_edge': *, 'synapse': *}, (217, 218): {'comp_edge': *, 'synapse': *}, (218, 219): {'comp_edge': *, 'synapse': *}, (218, 220): {'comp_edge': *, 'synapse': *}, (220, 221): {'comp_edge': *, 'synapse': *}, (221, 222): {'comp_edge': *, 'synapse': *}, (221, 223): {'comp_edge': *, 'synapse': *}, (227, 228): {'comp_edge': *, 'synapse': *}, (228, 229): {'comp_edge': *, 'synapse': *}, (228, 230): {'comp_edge': *, 'synapse': *}}, {'channels': {'test1': *, 'test2': *}, 'synapses': {'test1': *, 'test2': *}, 'xyzr': None}])))" - ] - }, - "execution_count": 239, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "jax.tree.flatten(morph_comps)" - ] - }, { "cell_type": "code", "execution_count": 356, From 31868fd2d681379dc48e80e116c1db4d98cf4628 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Fri, 30 May 2025 18:08:11 +0200 Subject: [PATCH 15/24] wip: save wip --- dev.ipynb | 212 ++++++++++++++++++++---------------------------------- 1 file changed, 77 insertions(+), 135 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index fd14d8358..2d9d02157 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -41,12 +41,14 @@ "from jax import vmap\n", "\n", "from typing import Optional, List, Dict, Any, Union, Set, Tuple\n", - "from dataclasses import dataclass, field" + "from dataclasses import dataclass, field\n", + "\n", + "from jaxley.io.graph import _build_module_scaffold" ] }, { "cell_type": "code", - "execution_count": 141, + "execution_count": 384, "metadata": {}, "outputs": [], "source": [ @@ -340,11 +342,11 @@ " branch_tips = branch[0], branch[-1]\n", " branch_tip_attrs = [[i, True, node_attrs[\"id\"].iloc[0], 0],\n", " [i, True, node_attrs[\"id\"].iloc[-1], 0]]\n", - " comp_attrs = [i, False, branch_id, comp_len]*num_comps\n", + " comp_attrs = [[i, False, branch_id, comp_len]]*num_comps\n", "\n", " comp_inds = proposed_comp_inds[i*num_comps:(i+1)*num_comps]\n", " comp_inds = np.array([branch_tips[0], *comp_inds, branch_tips[1]])\n", - " comp_attrs = [branch_tip_attrs[0]] + [comp_attrs] + [branch_tip_attrs[1]]\n", + " comp_attrs = [branch_tip_attrs[0]] + comp_attrs + [branch_tip_attrs[1]]\n", " comp_attrs = np.hstack([comp_inds[:, None], comp_attrs])\n", " \n", " # Interpolate xyzr coordinates and combine with attributes\n", @@ -363,9 +365,9 @@ " branch_nodes.append(comp_attrs)\n", "\n", " branch_nodes = jnp.concatenate(branch_nodes)\n", - " comp_attrs_keys = [\"idx\", \"branch_index\", \"branchpoint\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", + " comp_attrs_keys = [\"idx\", \"branch\", \"branchpoint\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", - " int_cols = [\"idx\", \"branch_index\", \"id\"] # TODO: rename to branch!\n", + " int_cols = [\"idx\", \"branch\", \"id\"]\n", " bool_cols = [\"branchpoint\"]\n", " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", " comp_df[bool_cols] = comp_df[bool_cols].astype(bool)\n", @@ -383,25 +385,32 @@ " comp_tree = comp_tree.reindex_nodes(dict(zip(comp_df.index, range(len(comp_df)))))\n", " return comp_tree\n", "\n", - "def _add_meta_data(tree: MorphTree) -> MorphTree:\n", + "def _add_jaxley_meta_data(tree: MorphTree) -> MorphTree:\n", " group_ids = {0: \"undefined\", 1: \"soma\", 2: \"axon\", 3: \"basal\", 4: \"apical\"}\n", - " fill_w = lambda x: np.full(len(tree.nodes), x)\n", "\n", " nodes_df, edge_df, global_attrs = tree.to_pandas()\n", " global_attrs = pd.concat([global_attrs, pd.Series({\"channels\": {}, \"synapses\": {}})])\n", " \n", - " nodes_df[\"cell_index\"] = fill_w(0) # rename to cell\n", - " nodes_df[\"comp_index\"] = np.arange(len(nodes_df)) # rename to comp\n", - " nodes_df[\"id\"] = nodes_df[\"id\"].apply(lambda x: [group_ids[x]])\n", - " nodes_df = nodes_df.rename(columns={\"r\": \"radius\", \"l\": \"length\", \"id\": \"groups\"})\n", - " nodes_df[\"capacitance\"] = fill_w(1.0)\n", - " nodes_df[\"v\"] = fill_w(-70.0)\n", - " nodes_df[\"axial_resistivity\"] = fill_w(1000.0)\n", + " # rename/reformat existing columns\n", + " nodes_df[\"groups\"] = nodes_df[\"id\"].apply(lambda x: [group_ids[x]])\n", + " nodes_df = nodes_df.drop(columns=[\"id\"])\n", + " nodes_df = nodes_df.rename({\"r\": \"radius\", \"l\": \"length\", \"branch\": \"branch_index\"}, axis=1)\n", + "\n", + " # new columns\n", + " nodes_df[\"capacitance\"] = 1.0\n", + " nodes_df[\"v\"] = -70.0\n", + " nodes_df[\"axial_resistivity\"] = 1000.0\n", + " #TODO: rename to cell_index > cell, comp_index > comp, branch_index > branch\n", + " nodes_df[\"comp_index\"] = np.arange(len(nodes_df))\n", + " nodes_df[\"cell_index\"] = 0\n", "\n", " return MorphTree.from_pandas(nodes_df, edge_df, global_attrs)\n", "\n", - "def _remove_branchpoints(tree: MorphTree) -> MorphTree:\n", + "def _replace_branchpoints_with_edges(tree: MorphTree) -> MorphTree:\n", " G = tree.to_nx()\n", + " G.add_edges_from([(i, j, {\"branch_edge\": False}) for i, j in G.edges])\n", + " branch_edge_attrs = {\"comp_edge\": True, \"synapse\": False, \"branch_edge\": True}\n", + "\n", " branchpoints = [n for n in G.nodes if G.nodes[n][\"branchpoint\"]]\n", " for n in branchpoints:\n", " parent = next(G.predecessors(n))\n", @@ -409,112 +418,59 @@ " \n", " # remove branchpoint and connect parent to children\n", " G.remove_node(n)\n", - " G.add_edges_from([(parent, c) for c in children], comp_edge=True, synapse=False)\n", + " G.add_edges_from([(parent, c) for c in children], **branch_edge_attrs)\n", " \n", - " tree = MorphTree.from_nx(G)\n", - " for n in tree.node_attrs:\n", - " tree.node_attrs[n].pop(\"branchpoint\")\n", - " # TODO: relabel comps?\n", - " return tree" - ] - }, - { - "cell_type": "code", - "execution_count": 142, - "metadata": {}, - "outputs": [], - "source": [ - "from jaxley.io.graph import _build_module_scaffold\n", - "\n", - "def _build_module(\n", - " solve_graph: nx.DiGraph,\n", - " assign_groups: bool = True,\n", - "):\n", - " # nodes and edges\n", - " node_df = pd.DataFrame(\n", - " [d for i, d in solve_graph.nodes(data=True)], index=solve_graph.nodes\n", - " ).sort_index()\n", - "\n", - " edge_type = nx.get_edge_attributes(solve_graph, \"type\")\n", - " synapse_edges = pd.DataFrame(\n", - " [\n", - " {\n", - " \"pre_index\": i,\n", - " \"post_index\": j,\n", - " **solve_graph.edges[i, j],\n", - " }\n", - " for (i, j), t in edge_type.items()\n", - " if t == \"synapse\"\n", - " ]\n", - " )\n", + " for i, n in enumerate(G.nodes):\n", + " G.nodes[n].pop(\"branchpoint\")\n", + " # TODO: skip relabeling comps?\n", + " G.nodes[n][\"comp_index\"] = i\n", + " G = nx.relabel_nodes(G, {n: i for i, n in enumerate(G.nodes)})\n", + " \n", + " return MorphTree.from_nx(G)\n", "\n", - " # branches\n", - " branch_of_node = lambda i: solve_graph.nodes[i][\"branch_index\"]\n", - " branch_edges_df = pd.DataFrame(\n", - " [\n", - " (branch_of_node(i), branch_of_node(j))\n", - " for (i, j), t in edge_type.items()\n", - " if t == \"inter_branch\"\n", - " ],\n", - " columns=[\"parent_branch_index\", \"child_branch_index\"],\n", - " )\n", + "def _compute_branch_parents(node_df, edge_df):\n", + " branch_edge_inds = edge_df.index[edge_df[\"branch_edge\"]]\n", "\n", - " # drop special attrs from nodes and ignore error if col does not exist\n", - " # x,y,z can be re-computed from xyzr if needed\n", - " optional_attrs = [\n", - " \"recordings\",\n", - " \"externals\",\n", - " \"external_inds\",\n", - " \"trainable\",\n", - " ]\n", - " node_df = node_df.drop(columns=optional_attrs, errors=\"ignore\")\n", + " parent_inds = branch_edge_inds.get_level_values(0)\n", + " child_inds = branch_edge_inds.get_level_values(1)\n", "\n", - " # synapses\n", - " synapse_edges = synapse_edges.drop([\"l\", \"type\"], axis=1, errors=\"ignore\")\n", - " synapse_edges = synapse_edges.rename({\"syn_type\": \"type\"}, axis=1)\n", - " synapse_edges.rename({\"edge_index\": \"global_edge_index\"}, axis=1, inplace=True)\n", + " branch_edges = pd.DataFrame({\n", + " \"parent_branch\": node_df[\"branch_index\"].loc[parent_inds].values,\n", + " \"child_branch\": node_df[\"branch_index\"].loc[child_inds].values\n", + " })\n", "\n", - " # build module\n", " acc_parents = []\n", - " parent_branch_inds = branch_edges_df.set_index(\"child_branch_index\").sort_index()[\n", - " \"parent_branch_index\"\n", - " ]\n", - " assert np.std(node_df.groupby(\"branch_index\").size().to_numpy()) < 1e-8, (\n", - " \"`from_graph()` does not support a varying number of compartments in each \"\n", - " \"branch.\"\n", - " )\n", + " parent_branch_inds = branch_edges.set_index(\"child_branch\").sort_index()[\"parent_branch\"]\n", + "\n", " for branch_inds in node_df.groupby(\"cell_index\")[\"branch_index\"].unique():\n", " root_branch_idx = branch_inds[0]\n", " parents = parent_branch_inds.loc[branch_inds[1:]] - root_branch_idx\n", " acc_parents.append([-1] + parents.tolist())\n", + " return acc_parents\n", + "\n", + "def _build_module(morph_comps: MorphTree) -> Module:\n", + " node_df, edge_df, global_attrs = morph_comps.to_pandas()\n", + " acc_parents = _compute_branch_parents(node_df, edge_df)\n", "\n", - " # TODO: support inhom ncomps\n", - " module = _build_module_scaffold(\n", - " node_df, solve_graph.graph[\"type\"], acc_parents, solve_graph.graph[\"xyzr\"]\n", + " assert np.std(node_df.groupby(\"branch_index\").size().to_numpy()) < 1e-8, (\n", + " \"`from_graph()` does not support a varying number of compartments in each \"\n", + " \"branch.\"\n", " )\n", + " module = _build_module_scaffold(node_df, parent_branches=acc_parents, xyzr=global_attrs[\"xyzr\"])\n", "\n", - " # set global attributes of module. `xyzr` is passed here again, although it has\n", - " # already been passed to `_build_module_scaffold`. `jx.Cell` requires xyzr at\n", - " # __init__()`, all other modules do not.\n", - " for k, v in solve_graph.graph.items():\n", - " if k not in [\"type\"]:\n", - " setattr(module, k, v)\n", - "\n", - " if assign_groups and \"groups\" in node_df.columns:\n", - " groups = node_df.pop(\"groups\").explode()\n", - " groups = (\n", - " pd.DataFrame(groups)\n", - " .groupby(\"groups\")\n", - " .apply(lambda x: x.index.values, include_groups=False)\n", - " .to_dict()\n", - " )\n", - " for group_name, group_inds in groups.items():\n", - " module.select(nodes=group_inds).add_to_group(group_name)\n", + " groups_df = node_df.groups.explode()\n", + " groups = groups_df.groupby(groups_df).groups\n", + " for group_name, group_inds in groups.items():\n", + " module.select(nodes=group_inds).add_to_group(group_name)\n", + " node_df.drop(columns=[\"groups\"], inplace=True)\n", + "\n", + " synapse_edges = edge_df[edge_df.synapse]\n", "\n", " node_df.columns = [\n", " \"global_\" + col if \"local\" not in col and \"index\" in col else col\n", " for col in node_df.columns\n", " ]\n", + "\n", " # set column-wise. preserves cols not in df.\n", " module.nodes[node_df.columns] = node_df\n", " module.edges = synapse_edges if not synapse_edges.empty else module.edges\n", @@ -522,49 +478,35 @@ " # add all the extra attrs\n", " module.membrane_current_names = [c.current_name for c in module.channels]\n", " module.synapse_names = [s._name for s in module.synapses]\n", - "\n", " return module" ] }, { "cell_type": "code", - "execution_count": 143, + "execution_count": 385, "metadata": {}, "outputs": [], "source": [ "morph_tree = swc_to_morph_tree(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", "morph_comps = compartmentalize(morph_tree, num_comps=1)\n", - "morph_comps = _add_meta_data(morph_comps)\n", - "morph_comps = _remove_branchpoints(morph_comps)" + "morph_comps = _add_jaxley_meta_data(morph_comps)\n", + "morph_comps = _replace_branchpoints_with_edges(morph_comps)\n", + "cell = _build_module(morph_comps)" ] }, { "cell_type": "code", - "execution_count": 144, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "ename": "KeyError", - "evalue": "\"None of [Index([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,\\n ...\\n 145, 146, 147, 148, 149, 150, 151, 152, 153, 154],\\n dtype='int64', name='child_branch_index', length=154)] are in the [index]\"", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[144], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43m_build_module\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmorph_comps\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mto_nx\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n", - "Cell \u001b[0;32mIn[142], line 62\u001b[0m, in \u001b[0;36m_build_module\u001b[0;34m(solve_graph, assign_groups)\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m branch_inds \u001b[38;5;129;01min\u001b[39;00m node_df\u001b[38;5;241m.\u001b[39mgroupby(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcell_index\u001b[39m\u001b[38;5;124m\"\u001b[39m)[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbranch_index\u001b[39m\u001b[38;5;124m\"\u001b[39m]\u001b[38;5;241m.\u001b[39munique():\n\u001b[1;32m 61\u001b[0m root_branch_idx \u001b[38;5;241m=\u001b[39m branch_inds[\u001b[38;5;241m0\u001b[39m]\n\u001b[0;32m---> 62\u001b[0m parents \u001b[38;5;241m=\u001b[39m \u001b[43mparent_branch_inds\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mloc\u001b[49m\u001b[43m[\u001b[49m\u001b[43mbranch_inds\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m]\u001b[49m\u001b[43m]\u001b[49m \u001b[38;5;241m-\u001b[39m root_branch_idx\n\u001b[1;32m 63\u001b[0m acc_parents\u001b[38;5;241m.\u001b[39mappend([\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m] \u001b[38;5;241m+\u001b[39m parents\u001b[38;5;241m.\u001b[39mtolist())\n\u001b[1;32m 65\u001b[0m \u001b[38;5;66;03m# TODO: support inhom ncomps\u001b[39;00m\n", - "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexing.py:1191\u001b[0m, in \u001b[0;36m_LocationIndexer.__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 1189\u001b[0m maybe_callable \u001b[38;5;241m=\u001b[39m com\u001b[38;5;241m.\u001b[39mapply_if_callable(key, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj)\n\u001b[1;32m 1190\u001b[0m maybe_callable \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_check_deprecated_callable_usage(key, maybe_callable)\n\u001b[0;32m-> 1191\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_getitem_axis\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmaybe_callable\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexing.py:1420\u001b[0m, in \u001b[0;36m_LocIndexer._getitem_axis\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1417\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(key, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mndim\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;129;01mand\u001b[39;00m key\u001b[38;5;241m.\u001b[39mndim \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m 1418\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCannot index with multidimensional key\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m-> 1420\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_getitem_iterable\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1422\u001b[0m \u001b[38;5;66;03m# nested tuple slicing\u001b[39;00m\n\u001b[1;32m 1423\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_nested_tuple(key, labels):\n", - "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexing.py:1360\u001b[0m, in \u001b[0;36m_LocIndexer._getitem_iterable\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1357\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_validate_key(key, axis)\n\u001b[1;32m 1359\u001b[0m \u001b[38;5;66;03m# A collection of keys\u001b[39;00m\n\u001b[0;32m-> 1360\u001b[0m keyarr, indexer \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_listlike_indexer\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1361\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39m_reindex_with_indexers(\n\u001b[1;32m 1362\u001b[0m {axis: [keyarr, indexer]}, copy\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m, allow_dups\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 1363\u001b[0m )\n", - "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexing.py:1558\u001b[0m, in \u001b[0;36m_LocIndexer._get_listlike_indexer\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1555\u001b[0m ax \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39m_get_axis(axis)\n\u001b[1;32m 1556\u001b[0m axis_name \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39m_get_axis_name(axis)\n\u001b[0;32m-> 1558\u001b[0m keyarr, indexer \u001b[38;5;241m=\u001b[39m \u001b[43max\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_indexer_strict\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis_name\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1560\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m keyarr, indexer\n", - "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexes/base.py:6200\u001b[0m, in \u001b[0;36mIndex._get_indexer_strict\u001b[0;34m(self, key, axis_name)\u001b[0m\n\u001b[1;32m 6197\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 6198\u001b[0m keyarr, indexer, new_indexer \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_reindex_non_unique(keyarr)\n\u001b[0;32m-> 6200\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_raise_if_missing\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkeyarr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mindexer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis_name\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 6202\u001b[0m keyarr \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtake(indexer)\n\u001b[1;32m 6203\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(key, Index):\n\u001b[1;32m 6204\u001b[0m \u001b[38;5;66;03m# GH 42790 - Preserve name from an Index\u001b[39;00m\n", - "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/pandas/core/indexes/base.py:6249\u001b[0m, in \u001b[0;36mIndex._raise_if_missing\u001b[0;34m(self, key, indexer, axis_name)\u001b[0m\n\u001b[1;32m 6247\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m nmissing:\n\u001b[1;32m 6248\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m nmissing \u001b[38;5;241m==\u001b[39m \u001b[38;5;28mlen\u001b[39m(indexer):\n\u001b[0;32m-> 6249\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNone of [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mkey\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m] are in the [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00maxis_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m]\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 6251\u001b[0m not_found \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(ensure_index(key)[missing_mask\u001b[38;5;241m.\u001b[39mnonzero()[\u001b[38;5;241m0\u001b[39m]]\u001b[38;5;241m.\u001b[39munique())\n\u001b[1;32m 6252\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnot_found\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m not in index\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "\u001b[0;31mKeyError\u001b[0m: \"None of [Index([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,\\n ...\\n 145, 146, 147, 148, 149, 150, 151, 152, 153, 154],\\n dtype='int64', name='child_branch_index', length=154)] are in the [index]\"" - ] - } - ], - "source": [ - "_build_module(morph_comps.to_nx())" - ] + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] }, { "cell_type": "code", From 59bb49cec0344238f404e1ed16f709bd748daae8 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Fri, 30 May 2025 18:26:43 +0200 Subject: [PATCH 16/24] enh: import pipeline from swc to module is working now --- dev.ipynb | 65 +++++++++++-------------------------------------------- 1 file changed, 13 insertions(+), 52 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index 2d9d02157..c6ca78803 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 384, + "execution_count": 407, "metadata": {}, "outputs": [], "source": [ @@ -193,6 +193,7 @@ " def soma_nodes() -> bool:\n", " return [i for i, n in G.nodes.items() if n[\"id\"] == 1]\n", "\n", + "\n", " def walk_path(start: int, succ: int) -> List[int]:\n", " path = [start, succ]\n", " visited.add((start, succ))\n", @@ -280,7 +281,7 @@ " recurse(root, theta=0.0, phi=np.pi/2)\n", " return pos\n", "\n", - "def _add_missing_attrs(tree: MorphTree) -> MorphTree:\n", + "def _add_missing_swc_attrs(tree: MorphTree) -> MorphTree:\n", " defaults = {\"id\": 0, \"r\": 1}\n", " node_attr_keys = next(iter(tree.node_attrs.values())).keys()\n", " xyz = compute_xyz(tree) if \"x\" not in node_attr_keys else {}\n", @@ -295,7 +296,7 @@ " return tree\n", "\n", "def compartmentalize(tree: MorphTree, num_comps: int = 1) -> MorphTree:\n", - " tree = _add_missing_attrs(tree)\n", + " tree = _add_missing_swc_attrs(tree)\n", "\n", " branches = list_branches(tree)\n", " nodes_df = tree.to_pandas()[0].astype(float)\n", @@ -422,7 +423,7 @@ " \n", " for i, n in enumerate(G.nodes):\n", " G.nodes[n].pop(\"branchpoint\")\n", - " # TODO: skip relabeling comps?\n", + " # TODO: Can we skip relabeling comps and reindexing the dataframe?\n", " G.nodes[n][\"comp_index\"] = i\n", " G = nx.relabel_nodes(G, {n: i for i, n in enumerate(G.nodes)})\n", " \n", @@ -452,11 +453,13 @@ " node_df, edge_df, global_attrs = morph_comps.to_pandas()\n", " acc_parents = _compute_branch_parents(node_df, edge_df)\n", "\n", - " assert np.std(node_df.groupby(\"branch_index\").size().to_numpy()) < 1e-8, (\n", + " nodes_per_branch = node_df[\"branch_index\"].value_counts()\n", + " assert nodes_per_branch.nunique() == 1, (\n", " \"`from_graph()` does not support a varying number of compartments in each \"\n", " \"branch.\"\n", " )\n", " module = _build_module_scaffold(node_df, parent_branches=acc_parents, xyzr=global_attrs[\"xyzr\"])\n", + " # TODO: MorphTree backend, it should be possible to the MorphTree into the Module\n", "\n", " groups_df = node_df.groups.explode()\n", " groups = groups_df.groupby(groups_df).groups\n", @@ -464,18 +467,20 @@ " module.select(nodes=group_inds).add_to_group(group_name)\n", " node_df.drop(columns=[\"groups\"], inplace=True)\n", "\n", - " synapse_edges = edge_df[edge_df.synapse]\n", - "\n", " node_df.columns = [\n", " \"global_\" + col if \"local\" not in col and \"index\" in col else col\n", " for col in node_df.columns\n", " ]\n", "\n", + " synapse_edges = edge_df[edge_df.synapse]\n", + "\n", " # set column-wise. preserves cols not in df.\n", " module.nodes[node_df.columns] = node_df\n", " module.edges = synapse_edges if not synapse_edges.empty else module.edges\n", "\n", " # add all the extra attrs\n", + " module.synapses = global_attrs[\"synapses\"]\n", + " module.channels = global_attrs[\"channels\"]\n", " module.membrane_current_names = [c.current_name for c in module.channels]\n", " module.synapse_names = [s._name for s in module.synapses]\n", " return module" @@ -483,7 +488,7 @@ }, { "cell_type": "code", - "execution_count": 385, + "execution_count": 408, "metadata": {}, "outputs": [], "source": [ @@ -522,50 +527,6 @@ "outputs": [], "source": [] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 390, - "metadata": {}, - "outputs": [ - { - "ename": "ValueError", - "evalue": "setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (3,) + inhomogeneous part.", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[390], line 14\u001b[0m\n\u001b[1;32m 3\u001b[0m edges \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 4\u001b[0m (\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m), (\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m2\u001b[39m), (\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m3\u001b[39m), \u001b[38;5;66;03m# root 0 branches to 1, 2, 3\u001b[39;00m\n\u001b[1;32m 5\u001b[0m (\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m4\u001b[39m), (\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m5\u001b[39m), \u001b[38;5;66;03m# node 1 branches to 4, 5\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 10\u001b[0m (\u001b[38;5;241m9\u001b[39m, \u001b[38;5;241m14\u001b[39m), (\u001b[38;5;241m9\u001b[39m, \u001b[38;5;241m15\u001b[39m), (\u001b[38;5;241m9\u001b[39m, \u001b[38;5;241m16\u001b[39m) \u001b[38;5;66;03m# node 9 branches to 14, 15, 16\u001b[39;00m\n\u001b[1;32m 11\u001b[0m ]\n\u001b[1;32m 12\u001b[0m G\u001b[38;5;241m.\u001b[39madd_edges_from(edges)\n\u001b[0;32m---> 14\u001b[0m \u001b[43mcompartmentalize\u001b[49m\u001b[43m(\u001b[49m\u001b[43mMorphTree\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_nx\u001b[49m\u001b[43m(\u001b[49m\u001b[43mG\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnum_comps\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m2\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mplot()\n", - "Cell \u001b[0;32mIn[388], line 289\u001b[0m, in \u001b[0;36mcompartmentalize\u001b[0;34m(tree, num_comps)\u001b[0m\n\u001b[1;32m 287\u001b[0m comp_inds \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39marray([branch_tips[\u001b[38;5;241m0\u001b[39m], \u001b[38;5;241m*\u001b[39mcomp_inds, branch_tips[\u001b[38;5;241m1\u001b[39m]])\n\u001b[1;32m 288\u001b[0m comp_attrs \u001b[38;5;241m=\u001b[39m [branch_tip_attrs[\u001b[38;5;241m0\u001b[39m]] \u001b[38;5;241m+\u001b[39m [comp_attrs] \u001b[38;5;241m+\u001b[39m [branch_tip_attrs[\u001b[38;5;241m1\u001b[39m]]\n\u001b[0;32m--> 289\u001b[0m comp_attrs \u001b[38;5;241m=\u001b[39m \u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhstack\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcomp_inds\u001b[49m\u001b[43m[\u001b[49m\u001b[43m:\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcomp_attrs\u001b[49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 291\u001b[0m \u001b[38;5;66;03m# Interpolate xyzr coordinates and combine with attributes\u001b[39;00m\n\u001b[1;32m 292\u001b[0m x \u001b[38;5;241m=\u001b[39m jnp\u001b[38;5;241m.\u001b[39marray([\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m+\u001b[39m comp_locs \u001b[38;5;241m+\u001b[39m [branch_len]) \u001b[38;5;66;03m# 0, branch_len = branchpoints\u001b[39;00m\n", - "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/numpy/_core/shape_base.py:360\u001b[0m, in \u001b[0;36mhstack\u001b[0;34m(tup, dtype, casting)\u001b[0m\n\u001b[1;32m 295\u001b[0m \u001b[38;5;129m@array_function_dispatch\u001b[39m(_vhstack_dispatcher)\n\u001b[1;32m 296\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mhstack\u001b[39m(tup, \u001b[38;5;241m*\u001b[39m, dtype\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, casting\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msame_kind\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 297\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 298\u001b[0m \u001b[38;5;124;03m Stack arrays in sequence horizontally (column wise).\u001b[39;00m\n\u001b[1;32m 299\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 358\u001b[0m \n\u001b[1;32m 359\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 360\u001b[0m arrs \u001b[38;5;241m=\u001b[39m \u001b[43matleast_1d\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mtup\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 361\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(arrs, \u001b[38;5;28mtuple\u001b[39m):\n\u001b[1;32m 362\u001b[0m arrs \u001b[38;5;241m=\u001b[39m (arrs,)\n", - "File \u001b[0;32m~/Uni/PhD/projects/jaxleyverse/jaxley/.venv/lib/python3.12/site-packages/numpy/_core/shape_base.py:69\u001b[0m, in \u001b[0;36matleast_1d\u001b[0;34m(*arys)\u001b[0m\n\u001b[1;32m 67\u001b[0m res \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m 68\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m ary \u001b[38;5;129;01min\u001b[39;00m arys:\n\u001b[0;32m---> 69\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43masanyarray\u001b[49m\u001b[43m(\u001b[49m\u001b[43mary\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 70\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m result\u001b[38;5;241m.\u001b[39mndim \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 71\u001b[0m result \u001b[38;5;241m=\u001b[39m result\u001b[38;5;241m.\u001b[39mreshape(\u001b[38;5;241m1\u001b[39m)\n", - "\u001b[0;31mValueError\u001b[0m: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (3,) + inhomogeneous part." - ] - } - ], - "source": [ - "# TODO: FIX THIS\n", - "G = nx.DiGraph()\n", - "edges = [\n", - " (0, 1), (0, 2), (0, 3),\n", - " (1, 4), (1, 5),\n", - " (2, 6), (2, 7), (2, 8),\n", - " (3, 9),\n", - " (4, 10), (4, 11),\n", - " (7, 12), (7, 13),\n", - " (9, 14), (9, 15), (9, 16)\n", - "]\n", - "G.add_edges_from(edges)\n", - "\n", - "compartmentalize(MorphTree.from_nx(G), num_comps=2).plot()" - ] - }, { "cell_type": "code", "execution_count": 86, From 6bf400f7cb43a098f355969903c9fc2313d77bbd Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Fri, 30 May 2025 20:00:49 +0200 Subject: [PATCH 17/24] doc: add documentation --- dev.ipynb | 463 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 357 insertions(+), 106 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index c6ca78803..d8495af7a 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": 424, "metadata": {}, "outputs": [], "source": [ @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 425, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 426, "metadata": {}, "outputs": [], "source": [ @@ -41,6 +41,7 @@ "from jax import vmap\n", "\n", "from typing import Optional, List, Dict, Any, Union, Set, Tuple\n", + "from matplotlib.axes import Axes\n", "from dataclasses import dataclass, field\n", "\n", "from jaxley.io.graph import _build_module_scaffold" @@ -48,34 +49,35 @@ }, { "cell_type": "code", - "execution_count": 407, + "execution_count": 427, "metadata": {}, "outputs": [], "source": [ - "def swc_to_morph_tree(fname: str, num_lines: Optional[int] = None) -> MorphTree:\n", - " i_id_xyzr_p = np.loadtxt(fname)[:num_lines]\n", - " \n", - " node_attrs, edge_attrs = {}, {}\n", - " for i, id, x, y, z, r, p in i_id_xyzr_p.tolist(): # tolist: np.float64 -> float\n", - " node_attrs[int(i)] = {\"id\": int(id), \"x\": x, \"y\": y, \"z\": z, \"r\": r}\n", - " if p != -1:\n", - " edge_attrs[int(p), int(i)] = {}\n", - " \n", - " return MorphTree(node_attrs, edge_attrs)\n", - "\n", "@jax.tree_util.register_dataclass\n", "@dataclass\n", "class MorphTree:\n", + " \"\"\"MorphTree is a custom cataclass that holds the node and edge attributes of a morphology.\n", + " \n", + " MorphTree is used to store the node and edge attributes of a morphology / jaxley Module\n", + " as a pytree, to allow for easy manipulation of the Module / morphology parameters \n", + " using jax transformations.\n", + "\n", + " MorphTree also allows for easy conversion to and from pandas DataFrames, and networkx \n", + " DiGraphs, as well as basic convenience functions for plotting and renaming or reordering\n", + " of nodes and edges.\n", + " \"\"\"\n", " node_attrs: Dict[int, Dict[str, Any]]\n", " edge_attrs: Dict[Tuple[int, int], Dict[str, Any]]\n", " global_attrs: Dict[str, Any] = field(default_factory=dict)\n", "\n", " @property\n", " def nodes(self) -> jnp.ndarray:\n", + " \"\"\"Returns the node indices as a jax array.\"\"\"\n", " return jnp.array(list(self.node_attrs.keys())).astype(int)\n", "\n", " @property\n", " def edges(self) -> jnp.ndarray:\n", + " \"\"\"Returns the edge indices as a jax array.\"\"\"\n", " return jnp.array(list(self.edge_attrs.keys())).astype(int)\n", "\n", " def __repr__(self) -> str:\n", @@ -93,12 +95,15 @@ " return f\"MorphTree(nodes={n_nodes}*{node_attrs}, edges={n_edges}*{edge_attrs}, global={list(self.global_attrs.keys())})\"\n", " \n", " def node(self, i: int) -> Dict[str, Any]:\n", + " \"\"\"Returns the node attributes for the node with index i.\"\"\"\n", " return self.node_attrs[i]\n", " \n", " def edge(self, i: int, j: int) -> Dict[str, Any]:\n", + " \"\"\"Returns the edge attributes for the edge between nodes i and j.\"\"\"\n", " return self.edge_attrs[i, j]\n", " \n", " def to_nx(self) -> nx.DiGraph:\n", + " \"\"\"Returns the MorphTree as a networkx DiGraph.\"\"\"\n", " G = nx.DiGraph()\n", " G.add_nodes_from(self.node_attrs.items())\n", " G.add_edges_from((i, j, d) for (i, j), d in self.edge_attrs.items())\n", @@ -107,11 +112,13 @@ " \n", " @staticmethod\n", " def from_nx(G: nx.DiGraph) -> MorphTree:\n", + " \"\"\"Returns a MorphTree from a networkx DiGraph.\"\"\"\n", " node_attrs = {n: G.nodes[n] for n in G.nodes}\n", " edge_attrs = {(i, j): G.edges[i, j] for i, j in G.edges}\n", " return MorphTree(node_attrs, edge_attrs, G.graph)\n", " \n", " def to_pandas(self, return_global_attrs: bool = True) -> Tuple[pd.DataFrame, pd.DataFrame]:\n", + " \"\"\"Returns the MorphTree as a pandas DataFrame.\"\"\"\n", " node_df = pd.DataFrame(self.node_attrs.values(), index=self.node_attrs.keys())\n", " edge_df = pd.DataFrame(self.edge_attrs.values(), index=self.edge_attrs.keys())\n", " edge_index = pd.MultiIndex.from_arrays(np.array(self.edges).T)\n", @@ -123,21 +130,42 @@ " \n", " @staticmethod\n", " def from_pandas(node_df: pd.DataFrame, edge_df: pd.DataFrame, global_attrs: pd.Series = pd.Series()) -> MorphTree:\n", + " \"\"\"Returns a MorphTree from a pandas DataFrame.\"\"\"\n", " node_attrs = node_df.to_dict(orient=\"index\")\n", " edge_attrs = edge_df.to_dict(orient=\"index\")\n", " return MorphTree(node_attrs, edge_attrs, global_attrs.to_dict())\n", " \n", - " def plot(self, dims=(0,1),**kwargs: Any) -> None:\n", + " def plot(self, dims=(0,1), ax: Optional[Axes] = None, **kwargs: Any) -> Axes:\n", + " \"\"\"Uses networkx to plot the MorphTree.\n", + " \n", + " Args:\n", + " dims: Dimensions to plot (0:x, 1:y, 2:z).\n", + " ax: plt.Axes.\n", + " **kwargs: kwargs for networkx.draw.\n", + "\n", + " Returns:\n", + " The Axes object on which the MorphTree was plotted.\n", + " \"\"\"\n", " G = self.to_nx()\n", " pos = {}\n", " dims2axes = {0: \"x\", 1: \"y\", 2: \"z\"}\n", " for n, attr in G.nodes(data=True):\n", " if \"x\" in attr: # assume y is also present\n", " pos[n] = (attr[dims2axes[dims[0]]], attr[dims2axes[dims[1]]])\n", - " nx.draw(G, pos, with_labels=True, **kwargs)\n", - " plt.show()\n", + " \n", + " ax = ax if ax is not None else plt.gca()\n", + " nx.draw(G, pos, with_labels=True, ax=ax, **kwargs)\n", + " return ax\n", "\n", " def reindex_nodes(self, mapping: dict) -> MorphTree:\n", + " \"\"\"Reindexes the nodes of the MorphTree according to the mapping dictionary.\n", + " \n", + " Args:\n", + " mapping: A dict mapping the old to new node indices.\n", + "\n", + " Returns:\n", + " A new MorphTree with the nodes reindexed according to the mapping.\n", + " \"\"\"\n", " new_node_attrs = {mapping[i]: attrs for i, attrs in self.node_attrs.items()}\n", " \n", " new_edge_attrs = {}\n", @@ -146,12 +174,23 @@ " \n", " return MorphTree(new_node_attrs, new_edge_attrs, self.global_attrs)\n", " \n", - " def reorder_tree(self, new_order: np.ndarray) -> MorphTree:\n", + " def reorder_tree(self, new_order: jnp.ndarray) -> MorphTree:\n", + " \"\"\"Reorders the nodes of the MorphTree according to the new order.\n", + " \n", + " Edges are flipped to ensure they are always in ascending order.\n", + " \n", + " Args:\n", + " new_order: New node order. new_order[i] is the new index of node i.\n", + "\n", + " Returns:\n", + " A new MorphTree with the nodes reordered according to the new order.\n", + " \"\"\"\n", " # TODO: check this does what I think it does, i.e. change the edge orientation\n", " # in order of appearance of the nodes in self.nodes.\n", " edges = np.array(self.edges)\n", - " idx_i = np.where(edges[:,0] == new_order[:, None])[0]\n", - " idx_j = np.where(edges[:,1] == new_order[:, None])[0]\n", + " np_order = np.array(new_order)\n", + " idx_i = np.where(edges[:,0] == np_order[:, None])[0]\n", + " idx_j = np.where(edges[:,1] == np_order[:, None])[0]\n", " is_descending = ~(idx_i < idx_j)\n", " for (i,j) in edges[is_descending]:\n", " print(i,j)\n", @@ -159,19 +198,205 @@ " return self\n", " \n", " def subgraph(self, nodes: List[int]) -> MorphTree:\n", + " \"\"\"Returns a subset of nodes in the MorphTree.\n", + "\n", + " Edges are only included if both nodes are in the subgraph.\n", + " \n", + " Args:\n", + " nodes: List of node indices to include in the subgraph.\n", + "\n", + " Returns:\n", + " A new MorphTree containing only the specified nodes and their edges.\n", + " \"\"\"\n", " node_attrs_subset = {i: self.node_attrs[i] for i in nodes}\n", " edge_attrs_subset = {(i,j): attrs for (i,j), attrs in self.edge_attrs.items() if i in nodes and j in nodes}\n", " return MorphTree(node_attrs_subset, edge_attrs_subset, self.global_attrs)\n", + " \n", + "# -----------------\n", + "# utility functions\n", + "# -----------------\n", + "\n", + "def compute_xyz(tree: MorphTree, length: float = 1.0, spread: float = np.pi/8, spread_decay: float = 0.9, twist: float = 0.0, xy_only: bool = True) -> dict[int, tuple[float, float, float]]:\n", + " \"\"\"Compute xyz coordinates for a tree-like appearance of a MorphTree graph in 2D or 3D.\n", + " \n", + " Handles branches implicitly since nodes in a branch have 1 child.\n", + "\n", + " Args:\n", + " tree: The MorphTree to compute node xyz coordinates for.\n", + " length: The length of each edge.\n", + " spread: The opening angle at which the edges spread out.\n", + " spread_decay: Multiplicative decay factor for the opening angle / spread.\n", + " twist: Add additional twisting. Means fewer overlapping nodes in 3D projections.\n", + " xy_only: Whether to only compute the xy coordinates and fix the z-coordinate.\n", + "\n", + " Returns:\n", + " A dictionary mapping node indices to xyz coordinates.\n", + " \"\"\"\n", + " # TODO: Replace compute_xyz with this or vice versa, redundant!\n", + " G = tree.to_nx()\n", + " root = next(n for n, d in G.in_degree() if d == 0)\n", + " pos = {root: (0.0, 0.0, 0.0)}\n", + "\n", + " def recurse(node, depth=1, theta=0.0, phi=np.pi/2):\n", + " children = [n for n in G.successors(node) if n not in pos]\n", + " if not children: return\n", + " n = len(children)\n", + " curr_spread = spread * (spread_decay ** (depth - 1))\n", + " x0, y0, z0 = pos[node]\n", + " phi = np.pi/2 if xy_only else phi\n", + " base_theta = theta + depth * twist\n", + " if n == 1:\n", + " thetas, phis = [base_theta], [phi]\n", + " else:\n", + " if xy_only:\n", + " thetas = np.linspace(base_theta - curr_spread/2, base_theta + curr_spread/2, n)\n", + " phis = [phi] * n\n", + " else:\n", + " thetas = np.linspace(base_theta, base_theta + 2 * np.pi, n, endpoint=False)\n", + " phis = [phi - curr_spread] * n\n", + " for th, ph, child in zip(thetas, phis, children):\n", + " x = x0 + length * np.sin(ph) * np.cos(th)\n", + " y = y0 + length * np.sin(ph) * np.sin(th)\n", + " z = z0 + length * np.cos(ph) * (not xy_only)\n", + " pos[child] = (x, y, z)\n", + " recurse(child, depth + 1, th, ph)\n", + "\n", + " recurse(root, theta=0.0, phi=np.pi/2)\n", + " return pos" + ] + }, + { + "cell_type": "code", + "execution_count": 441, + "metadata": {}, + "outputs": [], + "source": [ + "def swc_to_morphtree(fname: str, num_lines: Optional[int] = None) -> MorphTree:\n", + " \"\"\"Read a SWC file and return a MorphTree.\n", + "\n", + " The graph is read such that each entry in the swc file becomes a graph node\n", + " with the column attributes (id, x, y, z, r). Then each node is connected to its\n", + " designated parent via an edge.\n", + "\n", + " Args:\n", + " fname: Path to the swc file.\n", + " num_lines: Number of lines to read from the file. If None, all lines are read.\n", + "\n", + " Returns:\n", + " A MorphTree of the traced morphology. It has attributes:\n", + " nodes: {'id': 1, 'x': 0.0, 'y': 0.0, 'z': 0.0, 'r': 1.0, 'p': -1}\n", + " edges: {}\n", + "\n", + " Example usage\n", + " ^^^^^^^^^^^^^\n", + "\n", + " ::\n", + "\n", + " from jaxley.io.graph swc_to_morph_tree\n", + " morphtree = swc_to_morph_tree(\"path_to_swc.swc\")\n", + " \"\"\"\n", + " i_id_xyzr_p = np.loadtxt(fname)[:num_lines]\n", + " \n", + " node_attrs, edge_attrs = {}, {}\n", + " for i, id, x, y, z, r, p in i_id_xyzr_p.tolist(): # tolist: np.float64 -> float\n", + " node_attrs[int(i)] = {\"id\": int(id), \"x\": x, \"y\": y, \"z\": z, \"r\": r}\n", + " if p != -1:\n", + " edge_attrs[int(p), int(i)] = {}\n", + " \n", + " return MorphTree(node_attrs, edge_attrs)\n", + "\n", + "def _find_swc_tracing_interruptions(tree: MorphTree) -> list[tuple[int, int]]:\n", + " \"\"\"Identify discontinuities in the swc tracing order.\n", + "\n", + " Some swc files contain artefacts, where tracing of the same neurite was done\n", + " in disconnected pieces. NEURON swc reader introduce a break in the trace at these \n", + " points, since they parse the file in order. This leads to split branches, which \n", + " should be one. This function identifies these points in the graph.\n", + "\n", + " Example swc file:\n", + " # branch 1\n", + " 1 1 0.0 0.0 0.0 1.0 -1\n", + " 2 1 1.0 0.0 0.0 1.0 1\n", + " 3 1 2.0 0.0 0.0 1.0 2\n", + " # branch 2\n", + " 4 2 3.0 1.0 0.0 1.0 3\n", + " 5 2 4.0 2.0 0.0 1.0 4\n", + " # branch 3\n", + " 6 3 3.0 -1.0 0.0 1.0 3\n", + " 7 3 4.0 -2.0 0.0 1.0 6\n", + " 8 3 5.0 -3.0 0.0 1.0 7\n", + " # ammend branch 2\n", + " 9 4 5.0 3.0 0.0 1.0 5\n", + "\n", + " Args:\n", + " tree: MorphTree tracing of swc file.\n", + "\n", + " Returns:\n", + " An array of edges where tracing is discontinous.\n", + " \"\"\"\n", + " G = tree.to_nx()\n", + " degree_is_2 = lambda n: G.out_degree(n) + G.in_degree(n) == 2\n", + "\n", + " interrupt_edges = []\n", + " for n in G.nodes:\n", + " if len(parents := list(G.predecessors(n))) > 0:\n", + " p = parents[0] \n", + " if p != n-1 and degree_is_2(n) and degree_is_2(p):\n", + " interrupt_edges.append((p,n))\n", + " return interrupt_edges\n", "\n", - "def list_branches(tree: MorphTree, return_branchpoints: bool = False) -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", + "def _split_branches(branches: list[list[int]], split_edges: list[tuple[int, int]]) -> list[list[int]]:\n", + " \"\"\"Split branches at the given edges.\n", + "\n", + " Args:\n", + " branches: List of branches, each represented as list of nodes.\n", + " split_edges: List of edges between nodes where tracing is discontinous.\n", + "\n", + " Returns:\n", + " An updated list of branches.\n", + " \"\"\"\n", + " for (p, n) in split_edges:\n", + " for i, branch in enumerate(branches):\n", + " if n in branch:\n", + " split_idx = branch.index(n)\n", + " branches[i:i+1] = [branch[:split_idx], branch[split_idx:]]\n", + " break\n", + " return branches\n", + "\n", + "def list_branches(tree: MorphTree, return_branchpoints: bool = False, ignore_swc_tracing_interruptions=True, relevant_ids: Optional[List[int]] = [1,2,3,4], max_len: Optional[float] = None) -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", + " \"\"\"Get all uninterrupted paths in the traced morphology (i.e. branches).\n", + "\n", + " The graph is traversed depth-first starting from the first found leaf node.\n", + " Nodes are considered to be part of a branch if they have only one parent and one\n", + " child, which are both of the same type (i.e. have the same `id`). Nodes which are\n", + " branchpoints or leafs are considered start / end points of a branch. A branchpoint\n", + " can start multiple branches.\n", + "\n", + " Args:\n", + " tree: MorphTree tracing of swc file.\n", + " return_branchpoints: Whether to return the branchpoints and edges between them\n", + " seperately.\n", + " ignore_swc_tracing_interruptions: Whether to ignore discontinuities in the swc\n", + " tracing order. If False, this will result in split branches at these points.\n", + " relevant_ids: All type ids that are not in this list will be ignored for\n", + " tracing the morphology. This means that branches which have multiple type\n", + " ids (which are not in `relevant_ids`) will be considered as one branch.\n", + " Defaults to `[1, 2, 3, 4]`.\n", + "\n", + " Returns:\n", + " A list of linear paths in the graph. Each path is represented as list of nodes.\n", + " \"\"\"\n", " G = tree.to_nx().to_undirected()\n", " branches = []\n", " branchpoints = set()\n", " visited = set()\n", "\n", + " in_visited = lambda n1, n2: (n1, n2) in visited or (n2, n1) in visited\n", + " id_of = lambda n: G.nodes[n][\"id\"]\n", + " is_soma = lambda n: id_of(n) == 1\n", + " soma_nodes = lambda: [i for i, n in G.nodes.items() if n[\"id\"] == 1]\n", + "\n", " def is_branchpoint_or_tip(n: int) -> bool:\n", - " is_leaf = G.degree(n) <= 1\n", - " is_branching = G.degree(n) > 2\n", " if G.degree(n) == 2:\n", " i,j = G.neighbors(n)\n", " # trace dir matters here! For segment with node IDs: [1, 1, 2, 2]\n", @@ -179,20 +404,15 @@ " # <- [[2,2], [2,1,1]] \n", " return not same_id(n, j)\n", " \n", + " is_leaf = G.degree(n) <= 1\n", + " is_branching = G.degree(n) > 2\n", " return is_leaf or is_branching\n", - "\n", - " def in_visited(n1: int, n2: int) -> bool:\n", - " return (n1, n2) in visited or (n2, n1) in visited\n", - "\n", - " def same_id(n1: int, n2: int) -> bool:\n", - " return G.nodes[n1][\"id\"] == G.nodes[n2][\"id\"] if \"id\" in G.nodes[n1] else True\n", - "\n", - " def is_soma(n: int) -> bool:\n", - " return G.nodes[n][\"id\"] == 1\n", " \n", - " def soma_nodes() -> bool:\n", - " return [i for i, n in G.nodes.items() if n[\"id\"] == 1]\n", - "\n", + " def same_id(n1: int, n2: int) -> bool:\n", + " has_id = lambda n: id_of(n) in relevant_ids if \"id\" in G.nodes[n] else False\n", + " if has_id(n1) and has_id(n2):\n", + " return id_of(n1) == id_of(n2)\n", + " return True\n", "\n", " def walk_path(start: int, succ: int) -> List[int]:\n", " path = [start, succ]\n", @@ -222,66 +442,32 @@ " if not in_visited(node, succ):\n", " branches.append(walk_path(node, succ))\n", " \n", + " # split branches\n", + " split_edges = []\n", + " if not ignore_swc_tracing_interruptions: # TODO: fix!\n", + " split_edges += _find_swc_tracing_interruptions(tree)\n", + " # TODO: add max_len\n", + " # if max_len is not None:\n", + "\n", + " branches = _split_branches(branches, split_edges)\n", + " branchpoints.update(set(p for (p,n) in split_edges))\n", + "\n", " if return_branchpoints:\n", " branchpoint_edges = sum([list(G.edges(n)) for n in branchpoints], [])\n", " return branches, branchpoints, branchpoint_edges\n", " return branches\n", "\n", - "def _find_swc_tracing_interruptions(tree: MorphTree) -> np.ndarray:\n", - " G = tree.to_nx()\n", - " degree_is_2 = lambda n: G.out_degree(n) + G.in_degree(n) == 2\n", - "\n", - " interrupt_edges = []\n", - " for n in G.nodes:\n", - " if len(parents := list(G.predecessors(n))) > 0:\n", - " p = parents[0] \n", - " if p != n-1 and degree_is_2(n) and degree_is_2(p):\n", - " interrupt_edges.append((p,n))\n", - " return interrupt_edges\n", - "\n", - "def _split_interrupted_branches(branches, split_edges) -> MorphTree:\n", - " for (p,n) in split_edges:\n", - " for i, branch in enumerate(branches):\n", - " if n in branch:\n", - " split_idx = branch.index(n)\n", - " branches[i:i+1] = [branch[:split_idx], branch[split_idx:]]\n", - " break\n", - " return branches\n", - "\n", - "def compute_xyz(tree: MorphTree, length=1.0, spread=np.pi/8, spread_decay=0.9, twist=0.0, xy_only=True):\n", - " # TODO: Replace compute_xyz with this or vice versa, redundant!\n", - " G = tree.to_nx()\n", - " root = next(n for n, d in G.in_degree() if d == 0)\n", - " pos = {root: (0.0, 0.0, 0.0)}\n", + "def _add_missing_swc_attrs(tree: MorphTree) -> MorphTree:\n", + " \"\"\"Add missing swc attributes to a MorphTree.\n", "\n", - " def recurse(node, depth=1, theta=0.0, phi=np.pi/2):\n", - " children = [n for n in G.successors(node) if n not in pos]\n", - " if not children: return\n", - " n = len(children)\n", - " curr_spread = spread * (spread_decay ** (depth - 1))\n", - " x0, y0, z0 = pos[node]\n", - " phi = np.pi/2 if xy_only else phi\n", - " base_theta = theta + depth * twist\n", - " if n == 1:\n", - " thetas, phis = [base_theta], [phi]\n", - " else:\n", - " if xy_only:\n", - " thetas = np.linspace(base_theta - curr_spread/2, base_theta + curr_spread/2, n)\n", - " phis = [phi] * n\n", - " else:\n", - " thetas = np.linspace(base_theta, base_theta + 2 * np.pi, n, endpoint=False)\n", - " phis = [phi - curr_spread] * n\n", - " for th, ph, child in zip(thetas, phis, children):\n", - " x = x0 + length * np.sin(ph) * np.cos(th)\n", - " y = y0 + length * np.sin(ph) * np.sin(th)\n", - " z = z0 + length * np.cos(ph) * (not xy_only)\n", - " pos[child] = (x, y, z)\n", - " recurse(child, depth + 1, th, ph)\n", + " Allows to specify morphology from just edges.\n", "\n", - " recurse(root, theta=0.0, phi=np.pi/2)\n", - " return pos\n", + " Args:\n", + " tree: The MorphTree to add missing attributes to.\n", "\n", - "def _add_missing_swc_attrs(tree: MorphTree) -> MorphTree:\n", + " Returns:\n", + " The MorphTree with missing attributes set to their defaults.\n", + " \"\"\"\n", " defaults = {\"id\": 0, \"r\": 1}\n", " node_attr_keys = next(iter(tree.node_attrs.values())).keys()\n", " xyz = compute_xyz(tree) if \"x\" not in node_attr_keys else {}\n", @@ -295,7 +481,51 @@ " tree.node_attrs[n].update(missing_attrs)\n", " return tree\n", "\n", - "def compartmentalize(tree: MorphTree, num_comps: int = 1) -> MorphTree:\n", + "def compartmentalize(tree: MorphTree, ncomp: int = 1, min_radius: Optional[float] = None, max_len: Optional[float] = None, ignore_swc_tracing_interruptions: bool = True, relevant_type_ids: Optional[List[int]] = None) -> MorphTree:\n", + " \"\"\"Return a networkX graph that indicates the compartment structure.\n", + "\n", + " Build a new graph made up of compartments in every branch. These compartments are\n", + " spaced at equidistant points along the branch. Node attributes, like radius are\n", + " linearly interpolated along its length.\n", + "\n", + " Example: 4 compartments | edges = - | nodes = o | comp_nodes = x\n", + " o-----------o----------o---o---o---o--------o\n", + " o-------x---o----x-----o--xo---o---ox-------o\n", + "\n", + " This function returns a MorphTree. The graph is directed only because every\n", + " compartment tracks the xyzr coordinates of the associated SWC file. These xyzr\n", + " coordinates are ordered by the order of the traversal of the swc_graph. In later\n", + " methods (e.g. build_solve_graph), we traverse the `comp_graph` and mostly ignore\n", + " the directionality of the edges, but we only use the directionality to reverse the\n", + " xyzr coordinates if necessary.\n", + "\n", + " Args:\n", + " swc_graph: Graph generated by `to_swc_graph()`.\n", + " ncomp: How many compartments per branch to insert.\n", + " root: The root branch from which to start tracing the nodes. This defines the\n", + " branch indices.\n", + " min_radius: Minimal radius for each compartment.\n", + " max_len: Maximal length for each branch. Longer branches are split into\n", + " separate branches.\n", + " ignore_swc_tracing_interruptions: If `False`, it this function automatically\n", + " starts a new branch when a section is traced with interruptions.\n", + " relevant_type_ids: All type ids that are not in this list will be ignored for\n", + " tracing the morphology. This means that branches which have multiple type\n", + " ids (which are not in `relevant_type_ids`) will be considered as one branch.\n", + " If `None`, we default to `[1, 2, 3, 4]`.\n", + "\n", + " Returns:\n", + " MorphTree of the compartmentalized morphology.\n", + "\n", + " Example usage\n", + " ^^^^^^^^^^^^^\n", + "\n", + " ::\n", + "\n", + " from jaxley.io.graph to_swc_morphtree\n", + " morphtree = to_swc_morphtree(\"path_to_swc.swc\")\n", + " comp_morphtree = compartmentalize(morphtree, ncomp=1)\n", + " \"\"\"\n", " tree = _add_missing_swc_attrs(tree)\n", "\n", " branches = list_branches(tree)\n", @@ -303,7 +533,7 @@ "\n", " # create new set of indices which arent already used as node indices to label comps\n", " existing_inds = set(nodes_df.index)\n", - " num_new_inds = len(branches)*num_comps\n", + " num_new_inds = len(branches)*ncomp\n", " proposed_inds = set(range(num_new_inds + len(existing_inds)))\n", " proposed_comp_inds = list(proposed_inds - existing_inds) # avoid overlap w. node indices\n", " \n", @@ -335,17 +565,17 @@ "\n", " branch_id = node_attrs[\"id\"].iloc[-1] # TODO: handle multi ids within branch!\n", " branch_len = max(node_attrs[\"l\"])\n", - " comp_len = branch_len / num_comps\n", - " comp_locs = list(np.linspace(comp_len/2, branch_len - comp_len/2, num_comps))\n", + " comp_len = branch_len / ncomp\n", + " comp_locs = list(np.linspace(comp_len/2, branch_len - comp_len/2, ncomp))\n", " \n", " # Create node indices and attributes\n", " # branch_inds, branchpoint, comp_id, comp_len\n", " branch_tips = branch[0], branch[-1]\n", " branch_tip_attrs = [[i, True, node_attrs[\"id\"].iloc[0], 0],\n", " [i, True, node_attrs[\"id\"].iloc[-1], 0]]\n", - " comp_attrs = [[i, False, branch_id, comp_len]]*num_comps\n", + " comp_attrs = [[i, False, branch_id, comp_len]]*ncomp\n", "\n", - " comp_inds = proposed_comp_inds[i*num_comps:(i+1)*num_comps]\n", + " comp_inds = proposed_comp_inds[i*ncomp:(i+1)*ncomp]\n", " comp_inds = np.array([branch_tips[0], *comp_inds, branch_tips[1]])\n", " comp_attrs = [branch_tip_attrs[0]] + comp_attrs + [branch_tip_attrs[1]]\n", " comp_attrs = np.hstack([comp_inds[:, None], comp_attrs])\n", @@ -372,6 +602,10 @@ " bool_cols = [\"branchpoint\"]\n", " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", " comp_df[bool_cols] = comp_df[bool_cols].astype(bool)\n", + "\n", + " # threshold radius\n", + " if min_radius is not None:\n", + " comp_df[\"r\"] = np.maximum(comp_df[\"r\"], min_radius)\n", " \n", " # drop duplicated branch nodes\n", " comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", @@ -387,6 +621,11 @@ " return comp_tree\n", "\n", "def _add_jaxley_meta_data(tree: MorphTree) -> MorphTree:\n", + " \"\"\"Add attributes to and rename existing attributes of the compartalized morphology.\n", + "\n", + " Makes the imported and compartmentalized morphology compatible with jaxley.\n", + " \"\"\"\n", + "\n", " group_ids = {0: \"undefined\", 1: \"soma\", 2: \"axon\", 3: \"basal\", 4: \"apical\"}\n", "\n", " nodes_df, edge_df, global_attrs = tree.to_pandas()\n", @@ -408,6 +647,7 @@ " return MorphTree.from_pandas(nodes_df, edge_df, global_attrs)\n", "\n", "def _replace_branchpoints_with_edges(tree: MorphTree) -> MorphTree:\n", + " \"\"\"Replace branchpoint nodes with edges connecting parent and children.\"\"\"\n", " G = tree.to_nx()\n", " G.add_edges_from([(i, j, {\"branch_edge\": False}) for i, j in G.edges])\n", " branch_edge_attrs = {\"comp_edge\": True, \"synapse\": False, \"branch_edge\": True}\n", @@ -429,9 +669,17 @@ " \n", " return MorphTree.from_nx(G)\n", "\n", - "def _compute_branch_parents(node_df, edge_df):\n", - " branch_edge_inds = edge_df.index[edge_df[\"branch_edge\"]]\n", + "def _compute_branch_parents(node_df: pd.DataFrame, edge_df: pd.DataFrame) -> List[List[int]]:\n", + " \"\"\"Compute the parent structure of the branch graph (for each cell).\n", + "\n", + " Args:\n", + " node_df: The node dataframe of the MorphTree.\n", + " edge_df: The edge dataframe of the MorphTree.\n", "\n", + " Returns:\n", + " The parent structure of the branch graph for each cell.\n", + " \"\"\"\n", + " branch_edge_inds = edge_df.index[edge_df[\"branch_edge\"]]\n", " parent_inds = branch_edge_inds.get_level_values(0)\n", " child_inds = branch_edge_inds.get_level_values(1)\n", "\n", @@ -450,6 +698,16 @@ " return acc_parents\n", "\n", "def _build_module(morph_comps: MorphTree) -> Module:\n", + " \"\"\"Build a Module from a compartmentalized morphology.\n", + "\n", + " This function builds a Module from a MorphTree.\n", + "\n", + " Args:\n", + " morph_comps: The MorphTree to build the Module from.\n", + "\n", + " Returns:\n", + " The Module built from the MorphTree.\n", + " \"\"\"\n", " node_df, edge_df, global_attrs = morph_comps.to_pandas()\n", " acc_parents = _compute_branch_parents(node_df, edge_df)\n", "\n", @@ -488,12 +746,12 @@ }, { "cell_type": "code", - "execution_count": 408, + "execution_count": 444, "metadata": {}, "outputs": [], "source": [ - "morph_tree = swc_to_morph_tree(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", - "morph_comps = compartmentalize(morph_tree, num_comps=1)\n", + "morph_tree = swc_to_morphtree(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", + "morph_comps = compartmentalize(morph_tree, ncomp=1)\n", "morph_comps = _add_jaxley_meta_data(morph_comps)\n", "morph_comps = _replace_branchpoints_with_edges(morph_comps)\n", "cell = _build_module(morph_comps)" @@ -520,13 +778,6 @@ "outputs": [], "source": [] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": 86, From 1a4ce4d92fdb224b7083043f4fa6d1ab4a9e0e82 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Tue, 10 Jun 2025 14:31:46 +0200 Subject: [PATCH 18/24] enh: remove MorphTree from swc reader --- dev.ipynb | 1388 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 1307 insertions(+), 81 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index d8495af7a..d8fe30e22 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 424, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 425, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 426, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -49,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 427, + "execution_count": 48, "metadata": {}, "outputs": [], "source": [ @@ -94,6 +94,12 @@ " edge_attrs = edge_keys if len(self.edge_attrs) > 0 else []\n", " return f\"MorphTree(nodes={n_nodes}*{node_attrs}, edges={n_edges}*{edge_attrs}, global={list(self.global_attrs.keys())})\"\n", " \n", + " def __iter__(self):\n", + " \"\"\"Allows unpacking of MorphTree as: node_attrs, edge_attrs, global_attrs = *tree\"\"\"\n", + " yield self.node_attrs\n", + " yield self.edge_attrs\n", + " yield self.global_attrs\n", + " \n", " def node(self, i: int) -> Dict[str, Any]:\n", " \"\"\"Returns the node attributes for the node with index i.\"\"\"\n", " return self.node_attrs[i]\n", @@ -262,12 +268,538 @@ " recurse(child, depth + 1, th, ph)\n", "\n", " recurse(root, theta=0.0, phi=np.pi/2)\n", - " return pos" + " return pos\n", + "\n", + "v_interp = vmap(jnp.interp, in_axes=(None, None, 1), out_axes=1)" ] }, { "cell_type": "code", - "execution_count": 441, + "execution_count": 303, + "metadata": {}, + "outputs": [], + "source": [ + "def pandas_to_nx(\n", + " node_attrs: pd.DataFrame,\n", + " edge_attrs: pd.DataFrame,\n", + " global_attrs: pd.Series\n", + ") -> nx.DiGraph:\n", + " \"\"\"Convert node_attrs, edge_attrs and global_attrs from pandas datatypes to a NetworkX DiGraph.\n", + " \n", + " Args:\n", + " node_attrs: DataFrame containing node attributes\n", + " edge_attrs: DataFrame containing edge attributes\n", + " global_attrs: Series containing global graph attributes\n", + " \n", + " Returns:\n", + " A directed graph with nodes, edges and global attributes from the input data.\n", + " \"\"\"\n", + " G = nx.from_pandas_edgelist(\n", + " edge_attrs.reset_index(), \n", + " source='level_0', \n", + " target='level_1', \n", + " edge_attr=True,\n", + " create_using=nx.DiGraph()\n", + " )\n", + " \n", + " nx.set_node_attributes(G, node_attrs.to_dict(orient='index'))\n", + " G.graph.update(global_attrs.to_dict())\n", + " return G\n", + "\n", + "def nx_to_pandas(G: nx.DiGraph) -> Tuple[pd.DataFrame, pd.DataFrame, pd.Series]:\n", + " \"\"\"Convert a NetworkX DiGraph to pandas datatypes.\n", + " \n", + " Args:\n", + " G: Input directed graph\n", + " \n", + " Returns:\n", + " Tuple containing:\n", + " - DataFrame of node attributes\n", + " - DataFrame of edge attributes\n", + " - Series of global graph attributes\n", + " \"\"\"\n", + " edge_df = nx.to_pandas_edgelist(G).set_index(['source', 'target'])\n", + " edge_df.index.names = [None, None]\n", + " node_df = pd.DataFrame.from_dict(dict(G.nodes(data=True)), orient='index')\n", + " \n", + " return node_df, edge_df, pd.Series(G.graph)\n", + "\n", + "\n", + "def swc_to_nx(fname: str, num_lines: Optional[int] = None) -> nx.DiGraph:\n", + " \"\"\"Read a SWC morphology file into a NetworkX DiGraph.\n", + " \n", + " Args:\n", + " fname: Path to the SWC file\n", + " num_lines: Number of lines to read from the file\n", + " \n", + " Returns:\n", + " A directed graph representing the morphology where:\n", + " - Nodes have attributes: id, x, y, z, r (radius)\n", + " - Edges represent parent-child relationships\n", + " \"\"\"\n", + " i_id_xyzr_p = np.loadtxt(fname)[:num_lines]\n", + "\n", + " graph = nx.DiGraph()\n", + " for i, id, x, y, z, r, p in i_id_xyzr_p.tolist(): # tolist: np.float64 -> float\n", + " graph.add_node(int(i), **{\"id\": int(id), \"x\": x, \"y\": y, \"z\": z, \"r\": r})\n", + " if p != -1:\n", + " graph.add_edge(int(p), int(i))\n", + " return graph\n", + "\n", + "def _split_branches(branches: list[list[int]], split_edges: list[tuple[int, int]]) -> list[list[int]]:\n", + " \"\"\"Split branches at the given edges.\n", + "\n", + " Args:\n", + " branches: List of branches, each represented as list of nodes.\n", + " split_edges: List of edges between nodes where tracing is discontinous.\n", + "\n", + " Returns:\n", + " An updated list of branches.\n", + " \"\"\"\n", + " for (p, n) in split_edges:\n", + " for i, branch in enumerate(branches):\n", + " if n in branch:\n", + " split_idx = branch.index(n)\n", + " branches[i:i+1] = [branch[:split_idx], branch[split_idx:]]\n", + " break\n", + " return branches\n", + "\n", + "def _find_swc_tracing_interruptions(G: nx.DiGraph) -> list[tuple[int, int]]:\n", + " \"\"\"Identify discontinuities in the swc tracing order.\n", + "\n", + " Some swc files contain artefacts, where tracing of the same neurite was done\n", + " in disconnected pieces. NEURON swc reader introduce a break in the trace at these \n", + " points, since they parse the file in order. This leads to split branches, which \n", + " should be one. This function identifies these points in the graph.\n", + "\n", + " Example swc file:\n", + " # branch 1\n", + " 1 1 0.0 0.0 0.0 1.0 -1\n", + " 2 1 1.0 0.0 0.0 1.0 1\n", + " 3 1 2.0 0.0 0.0 1.0 2\n", + " # branch 2\n", + " 4 2 3.0 1.0 0.0 1.0 3\n", + " 5 2 4.0 2.0 0.0 1.0 4\n", + " # branch 3\n", + " 6 3 3.0 -1.0 0.0 1.0 3\n", + " 7 3 4.0 -2.0 0.0 1.0 6\n", + " 8 3 5.0 -3.0 0.0 1.0 7\n", + " # ammend branch 2\n", + " 9 4 5.0 3.0 0.0 1.0 5\n", + "\n", + " Args:\n", + " G: NetworkX graph tracing of swc file.\n", + "\n", + " Returns:\n", + " An array of edges where tracing is discontinous.\n", + " \"\"\"\n", + " degree_is_2 = lambda n: G.out_degree(n) + G.in_degree(n) == 2\n", + "\n", + " interrupt_edges = []\n", + " for n in G.nodes:\n", + " if len(parents := list(G.predecessors(n))) > 0:\n", + " p = parents[0] \n", + " if p != n-1 and degree_is_2(n) and degree_is_2(p):\n", + " interrupt_edges.append((p,n))\n", + " return interrupt_edges\n", + "\n", + "def list_branches(G, return_branchpoints: bool = False, ignore_swc_tracing_interruptions=True, relevant_ids: Optional[List[int]] = [1,2,3,4], max_len: Optional[float] = None) -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", + " \"\"\"Get all uninterrupted paths in the traced morphology (i.e. branches).\n", + "\n", + " The graph is traversed depth-first starting from the first found leaf node.\n", + " Nodes are considered to be part of a branch if they have only one parent and one\n", + " child, which are both of the same type (i.e. have the same `id`). Nodes which are\n", + " branchpoints or leafs are considered start / end points of a branch. A branchpoint\n", + " can start multiple branches.\n", + "\n", + " Args:\n", + " G: NetworkX graph tracing of swc file.\n", + " return_branchpoints: Whether to return the branchpoints and edges between them\n", + " seperately.\n", + " ignore_swc_tracing_interruptions: Whether to ignore discontinuities in the swc\n", + " tracing order. If False, this will result in split branches at these points.\n", + " relevant_ids: All type ids that are not in this list will be ignored for\n", + " tracing the morphology. This means that branches which have multiple type\n", + " ids (which are not in `relevant_ids`) will be considered as one branch.\n", + " Defaults to `[1, 2, 3, 4]`.\n", + "\n", + " Returns:\n", + " A list of linear paths in the graph. Each path is represented as list of nodes.\n", + " \"\"\"\n", + " G = G.to_undirected()\n", + " branches = []\n", + " branchpoints = set()\n", + " visited = set()\n", + "\n", + " was_visited = lambda n1, n2: (n1, n2) in visited or (n2, n1) in visited\n", + " id_of = lambda n: G.nodes[n][\"id\"]\n", + " is_soma = lambda n: id_of(n) == 1\n", + " soma_nodes = lambda: [i for i, n in G.nodes.items() if n[\"id\"] == 1]\n", + "\n", + " def is_branchpoint_or_tip(n: int) -> bool:\n", + " if G.degree(n) == 2:\n", + " i,j = G.neighbors(n)\n", + " # trace dir matters here! For segment with node IDs: [1, 1, 2, 2]\n", + " # -> [[1,1], [1,2,2]] \n", + " # <- [[2,2], [2,1,1]] \n", + " return not same_id(n, j)\n", + " \n", + " is_leaf = G.degree(n) <= 1\n", + " is_branching = G.degree(n) > 2\n", + " return is_leaf or is_branching\n", + " \n", + " def same_id(n1: int, n2: int) -> bool:\n", + " has_id = lambda n: id_of(n) in relevant_ids if \"id\" in G.nodes[n] else False\n", + " if has_id(n1) and has_id(n2):\n", + " return id_of(n1) == id_of(n2)\n", + " return True\n", + "\n", + " def walk_path(start: int, succ: int) -> List[int]:\n", + " \"\"\"Walk from start to succ, recording new nodes until a branching node is hit.\"\"\"\n", + " path = [start, succ]\n", + " visited.add((start, succ))\n", + " \n", + " while G.degree(succ) == 2:\n", + " next_node = next(n for n in G.neighbors(succ) if n != path[-2])\n", + "\n", + " if was_visited(succ, next_node) or is_branchpoint_or_tip(succ):\n", + " break\n", + " \n", + " path.append(next_node)\n", + " visited.add((succ, next_node))\n", + " succ = next_node\n", + "\n", + " return path\n", + "\n", + " leaf = next(n for n in G.nodes if G.degree(n) == 1)\n", + " single_soma = len(soma_nodes()) == 1\n", + " for node in nx.dfs_tree(G, leaf):\n", + " if single_soma and is_soma(node):\n", + " branches.append([node])\n", + "\n", + " elif is_branchpoint_or_tip(node):\n", + " branchpoints.add(node)\n", + " for succ in G.neighbors(node):\n", + " if not was_visited(node, succ):\n", + " branches.append(walk_path(node, succ))\n", + " \n", + " # split branches\n", + " if not ignore_swc_tracing_interruptions: # TODO: fix!\n", + " split_edges = _find_swc_tracing_interruptions(G)\n", + " branches = _split_branches(branches, split_edges)\n", + " branchpoints.update(set(p for (p,n) in split_edges))\n", + " \n", + " # TODO: add max_len\n", + " if max_len is not None:\n", + " raise NotImplementedError(\"max_len not implemented\")\n", + "\n", + " if return_branchpoints:\n", + " branchpoint_edges = sum([list(G.edges(n)) for n in branchpoints], [])\n", + " return branches, branchpoints, branchpoint_edges\n", + " return branches\n", + "\n", + "def _add_missing_swc_attrs(G) -> nx.DiGraph:\n", + " \"\"\"Add missing swc attributes to a MorphTree.\n", + "\n", + " Allows to specify morphology from just edges.\n", + "\n", + " Args:\n", + " tree: The MorphTree to add missing attributes to.\n", + "\n", + " Returns:\n", + " The MorphTree with missing attributes set to their defaults.\n", + " \"\"\"\n", + " defaults = {\"id\": 0, \"r\": 1}\n", + " \n", + " available_keys = G.nodes[next(iter(G.nodes()))].keys()\n", + " xyz = compute_xyz(G) if \"x\" not in available_keys else {}\n", + " for n, (x, y, z) in xyz.items():\n", + " G.nodes[n][\"x\"] = x\n", + " G.nodes[n][\"y\"] = y\n", + " G.nodes[n][\"z\"] = z\n", + "\n", + " for key in set(defaults.keys()).difference(available_keys):\n", + " nx.set_node_attributes(G, defaults[key], key)\n", + " return G\n", + "\n", + "def compartmentalize(G: nx.DiGraph, ncomp: int = 1, min_radius: Optional[float] = None, max_len: Optional[float] = None, ignore_swc_tracing_interruptions: bool = True, relevant_type_ids: Optional[List[int]] = [1,2,3,4]) -> MorphTree:\n", + " \"\"\"Return a networkX graph that indicates the compartment structure.\n", + "\n", + " Build a new graph made up of compartments in every branch. These compartments are\n", + " spaced at equidistant points along the branch. Node attributes, like radius are\n", + " linearly interpolated along its length.\n", + "\n", + " Example: 4 compartments | edges = - | nodes = o | comp_nodes = x\n", + " o-----------o----------o---o---o---o--------o\n", + " o-------x---o----x-----o--xo---o---ox-------o\n", + "\n", + " This function returns a MorphTree. The graph is directed only because every\n", + " compartment tracks the xyzr coordinates of the associated SWC file. These xyzr\n", + " coordinates are ordered by the order of the traversal of the swc_graph. In later\n", + " methods (e.g. build_solve_graph), we traverse the `comp_graph` and mostly ignore\n", + " the directionality of the edges, but we only use the directionality to reverse the\n", + " xyzr coordinates if necessary.\n", + "\n", + " Args:\n", + " swc_graph: Graph generated by `to_swc_graph()`.\n", + " ncomp: How many compartments per branch to insert.\n", + " root: The root branch from which to start tracing the nodes. This defines the\n", + " branch indices.\n", + " min_radius: Minimal radius for each compartment.\n", + " max_len: Maximal length for each branch. Longer branches are split into\n", + " separate branches.\n", + " ignore_swc_tracing_interruptions: If `False`, it this function automatically\n", + " starts a new branch when a section is traced with interruptions.\n", + " relevant_type_ids: All type ids that are not in this list will be ignored for\n", + " tracing the morphology. This means that branches which have multiple type\n", + " ids (which are not in `relevant_type_ids`) will be considered as one branch.\n", + " If `None`, we default to `[1, 2, 3, 4]`.\n", + "\n", + " Returns:\n", + " MorphTree of the compartmentalized morphology.\n", + "\n", + " Example usage\n", + " ^^^^^^^^^^^^^\n", + "\n", + " ::\n", + "\n", + " from jaxley.io.graph to_swc_morphtree\n", + " morphtree = to_swc_morphtree(\"path_to_swc.swc\")\n", + " comp_morphtree = compartmentalize(morphtree, ncomp=1)\n", + " \"\"\"\n", + " G = _add_missing_swc_attrs(G)\n", + "\n", + " branches = list_branches(G, ignore_swc_tracing_interruptions=ignore_swc_tracing_interruptions, max_len=max_len, relevant_ids=relevant_type_ids)\n", + " nodes_df = nx_to_pandas(G)[0].astype(float)\n", + "\n", + " # create new set of indices which arent already used as node indices to label comps\n", + " existing_inds = set(nodes_df.index)\n", + " num_new_inds = len(branches)*ncomp\n", + " proposed_inds = set(range(num_new_inds + len(existing_inds)))\n", + " proposed_comp_inds = list(proposed_inds - existing_inds) # avoid overlap w. node indices\n", + " \n", + " # identify tip nodes (degree == 1 -> node appears only once in edges)\n", + " nodes_in_edges, node_counts_in_edges = np.unique(G.edges, return_counts=True)\n", + " tip_node_inds = nodes_in_edges[node_counts_in_edges == 1]\n", + "\n", + " # collect comps and comp_edges\n", + " branch_nodes, branch_edges = [], []\n", + " xyzr = []\n", + " for i, branch in enumerate(branches):\n", + " node_attrs = nodes_df.loc[branch]\n", + " xyzr_i = node_attrs[[\"x\", \"y\", \"z\", \"r\"]]\n", + " xyzr.append(xyzr_i.values)\n", + "\n", + " compute_edge_lens = lambda x: (x.diff(axis=0).fillna(0)**2).sum(axis=1)**.5\n", + " edge_lens = compute_edge_lens(xyzr_i[[\"x\", \"y\", \"z\"]])\n", + " node_attrs[\"l\"] = edge_lens.cumsum() # path length\n", + " \n", + " # For single-point somatata, we set l = 2*r this ensures\n", + " # A_cylinder = 2*pi*r*l = 4*pi*r^2 = A_sphere.\n", + " if len(branch) == 1:\n", + " node_attrs = node_attrs.loc[branch*2] # duplicate soma node\n", + " radius = node_attrs[\"r\"].iloc[0]\n", + " node_attrs[\"l\"] = np.array([0, 2*radius])\n", + "\n", + " branch_id = node_attrs[\"id\"].iloc[-1] # TODO: better handle mult. ids in branch!\n", + " branch_len = max(node_attrs[\"l\"])\n", + " comp_len = branch_len / ncomp\n", + " comp_locs = list(np.linspace(comp_len/2, branch_len - comp_len/2, ncomp))\n", + " \n", + " # Create node indices and attributes\n", + " # branch_inds, branchpoint, comp_id, comp_len\n", + " branch_tips = branch[0], branch[-1]\n", + " branch_tip_attrs = [[i, True, node_attrs[\"id\"].iloc[0], 0],\n", + " [i, True, node_attrs[\"id\"].iloc[-1], 0]]\n", + " comp_attrs = [[i, False, branch_id, comp_len]]*ncomp\n", + "\n", + " comp_inds = proposed_comp_inds[i*ncomp:(i+1)*ncomp]\n", + " comp_inds = np.array([branch_tips[0], *comp_inds, branch_tips[1]])\n", + " comp_attrs = [branch_tip_attrs[0]] + comp_attrs + [branch_tip_attrs[1]]\n", + " comp_attrs = np.hstack([comp_inds[:, None], comp_attrs])\n", + " \n", + " # Interpolate xyzr coordinates and combine with attributes\n", + " x = jnp.array([0] + comp_locs + [branch_len]) # 0, branch_len = branchpoints\n", + " xp = jnp.array(node_attrs[\"l\"].values)\n", + " fp = jnp.array(xyzr_i.values)\n", + " #TODO: interpolate r differently!\n", + " comp_attrs = np.hstack([comp_attrs, np.array(v_interp(x, xp, fp))])\n", + " \n", + " # remove tip nodes\n", + " comp_attrs = comp_attrs[1:] if branch_tips[0] in tip_node_inds else comp_attrs\n", + " comp_attrs = comp_attrs[:-1] if branch_tips[1] in tip_node_inds else comp_attrs\n", + "\n", + " # Store edges and nodes\n", + " branch_edges.append(list(zip(comp_attrs[:-1, 0], comp_attrs[1:, 0])))\n", + " branch_nodes.append(comp_attrs)\n", + "\n", + " branch_nodes = np.concatenate(branch_nodes)\n", + " comp_attrs_keys = [\"idx\", \"branch\", \"branchpoint\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", + " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", + " \n", + " int_cols = [\"idx\", \"branch\", \"id\"]\n", + " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", + " \n", + " bool_cols = [\"branchpoint\"]\n", + " comp_df[bool_cols] = comp_df[bool_cols].astype(bool)\n", + "\n", + " # threshold radius\n", + " if min_radius is not None:\n", + " comp_df[\"r\"] = np.maximum(comp_df[\"r\"], min_radius)\n", + " \n", + " # drop duplicated branch nodes\n", + " comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", + " comp_df = comp_df.set_index(\"idx\")\n", + "\n", + " # create comp edges\n", + " comp_edges = sum(branch_edges, [])\n", + " comp_edges_df = pd.DataFrame(index=pd.MultiIndex.from_tuples(comp_edges))\n", + " comp_edges_df[\"synapse\"] = False\n", + " comp_edges_df[\"comp_edge\"] = True\n", + "\n", + " global_attrs = pd.Series({\"xyzr\": xyzr})\n", + " G = pandas_to_nx(comp_df, comp_edges_df, global_attrs)\n", + " G = nx.relabel_nodes(G, {n: i for i, n in enumerate(G.nodes)})\n", + " return G\n", + "\n", + "def _add_jaxley_meta_data(G: MorphTree) -> MorphTree:\n", + " \"\"\"Add attributes to and rename existing attributes of the compartalized morphology.\n", + "\n", + " Makes the imported and compartmentalized morphology compatible with jaxley.\n", + " \"\"\"\n", + " nodes_df, edge_df, global_attrs = nx_to_pandas(G)\n", + " module_global_attrs = pd.Series({\"channels\": {}, \"synapses\": {}, \"group_names\": []})\n", + " global_attrs = pd.concat([global_attrs, module_global_attrs])\n", + " \n", + " # rename/reformat existing columns\n", + " group_ids = {0: \"undefined\", 1: \"soma\", 2: \"axon\", 3: \"basal\", 4: \"apical\"}\n", + " for group_id, group_name in group_ids.items():\n", + " where_group = nodes_df[\"id\"] == group_id\n", + " if where_group.any():\n", + " global_attrs[\"group_names\"].append(group_name)\n", + " nodes_df[group_name] = where_group\n", + " nodes_df = nodes_df.drop(columns=[\"id\"])\n", + " module_col_names = {\"r\": \"radius\", \"l\": \"length\", \"branch\": \"branch_index\"}\n", + " nodes_df = nodes_df.rename(module_col_names, axis=1)\n", + "\n", + " # new columns\n", + " nodes_df[\"capacitance\"] = 1.0\n", + " nodes_df[\"v\"] = -70.0\n", + " nodes_df[\"axial_resistivity\"] = 1000.0\n", + " #TODO: rename to cell_index > cell, comp_index > comp, branch_index > branch\n", + " nodes_df[\"comp_index\"] = np.arange(len(nodes_df))\n", + " nodes_df[\"cell_index\"] = 0\n", + "\n", + " return pandas_to_nx(nodes_df, edge_df, global_attrs)\n", + "\n", + "def _replace_branchpoints_with_edges(G: nx.DiGraph) -> nx.DiGraph:\n", + " \"\"\"Replace branchpoint nodes with edges connecting parent and children.\"\"\"\n", + " G.add_edges_from([(i, j, {\"branch_edge\": False}) for i, j in G.edges])\n", + " branch_edge_attrs = {\"comp_edge\": True, \"synapse\": False, \"branch_edge\": True}\n", + "\n", + " branchpoints = [n for n in G.nodes if G.nodes[n][\"branchpoint\"]]\n", + " for n in branchpoints:\n", + " parent = next(G.predecessors(n))\n", + " children = list(G.successors(n))\n", + " \n", + " # remove branchpoint and connect parent to children\n", + " G.remove_node(n)\n", + " G.add_edges_from([(parent, c) for c in children], **branch_edge_attrs)\n", + " \n", + " for i, n in enumerate(G.nodes):\n", + " G.nodes[n].pop(\"branchpoint\")\n", + " # TODO: Can we skip relabeling comps and reindexing the dataframe?\n", + " G.nodes[n][\"comp_index\"] = i\n", + " G = nx.relabel_nodes(G, {n: i for i, n in enumerate(G.nodes)})\n", + " \n", + " return G\n", + "\n", + "def _compute_branch_parents(node_df: pd.DataFrame, edge_df: pd.DataFrame) -> List[List[int]]:\n", + " \"\"\"Compute the parent structure of the branch graph (for each cell).\n", + "\n", + " Args:\n", + " node_df: The node dataframe of the MorphTree.\n", + " edge_df: The edge dataframe of the MorphTree.\n", + "\n", + " Returns:\n", + " The parent structure of the branch graph for each cell.\n", + " \"\"\"\n", + " branch_edge_inds = edge_df.index[edge_df[\"branch_edge\"]]\n", + " parent_inds = branch_edge_inds.get_level_values(0)\n", + " child_inds = branch_edge_inds.get_level_values(1)\n", + "\n", + " branch_edges = pd.DataFrame({\n", + " \"parent_branch\": node_df[\"branch_index\"].loc[parent_inds].values,\n", + " \"child_branch\": node_df[\"branch_index\"].loc[child_inds].values\n", + " })\n", + "\n", + " acc_parents = []\n", + " parent_branch_inds = branch_edges.set_index(\"child_branch\").sort_index()[\"parent_branch\"]\n", + "\n", + " for branch_inds in node_df.groupby(\"cell_index\")[\"branch_index\"].unique():\n", + " root_branch_idx = branch_inds[0]\n", + " parents = parent_branch_inds.loc[branch_inds[1:]] - root_branch_idx\n", + " acc_parents.append([-1] + parents.tolist())\n", + " return acc_parents\n", + "\n", + "def _build_module(G: nx.DiGraph) -> jx.Module:\n", + " \"\"\"Build a Module from a compartmentalized morphology.\n", + "\n", + " This function builds a Module from a MorphTree.\n", + "\n", + " Args:\n", + " G: The MorphTree to build the Module from.\n", + "\n", + " Returns:\n", + " The Module built from the MorphTree.\n", + " \"\"\"\n", + " node_df, edge_df, global_attrs = nx_to_pandas(G)\n", + "\n", + " nodes_per_branch = node_df[\"branch_index\"].value_counts()\n", + " assert nodes_per_branch.nunique() == 1, (\"`from_graph()` does not support a varying number of compartments in each branch.\")\n", + " \n", + " # TODO: MorphTree backend: read the MorphTree straight into the Module\n", + " acc_parents = _compute_branch_parents(node_df, edge_df)\n", + " module = _build_module_scaffold(node_df, parent_branches=acc_parents, xyzr=global_attrs[\"xyzr\"])\n", + "\n", + " # TODO: add groups\n", + "\n", + " node_df.columns = [\n", + " \"global_\" + col if \"local\" not in col and \"index\" in col else col\n", + " for col in node_df.columns\n", + " ]\n", + "\n", + " synapse_edges = edge_df[edge_df.synapse]\n", + "\n", + " # set column-wise. preserves cols not in df.\n", + " module.nodes[node_df.columns] = node_df\n", + " module.edges = synapse_edges if not synapse_edges.empty else module.edges\n", + "\n", + " # add all the extra attrs\n", + " module.synapses = global_attrs[\"synapses\"]\n", + " module.channels = global_attrs[\"channels\"]\n", + " module.membrane_current_names = [c.current_name for c in module.channels]\n", + " module.synapse_names = [s._name for s in module.synapses]\n", + " \n", + " return module" + ] + }, + { + "cell_type": "code", + "execution_count": 304, + "metadata": {}, + "outputs": [], + "source": [ + "morph_tree = swc_to_nx(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", + "morph_comps = compartmentalize(morph_tree, ncomp=1)\n", + "morph_comps = _add_jaxley_meta_data(morph_comps)\n", + "morph_comps = _replace_branchpoints_with_edges(morph_comps)\n", + "cell = _build_module(morph_comps)" + ] + }, + { + "cell_type": "code", + "execution_count": 113, "metadata": {}, "outputs": [], "source": [ @@ -391,7 +923,7 @@ " branchpoints = set()\n", " visited = set()\n", "\n", - " in_visited = lambda n1, n2: (n1, n2) in visited or (n2, n1) in visited\n", + " was_visited = lambda n1, n2: (n1, n2) in visited or (n2, n1) in visited\n", " id_of = lambda n: G.nodes[n][\"id\"]\n", " is_soma = lambda n: id_of(n) == 1\n", " soma_nodes = lambda: [i for i, n in G.nodes.items() if n[\"id\"] == 1]\n", @@ -415,13 +947,14 @@ " return True\n", "\n", " def walk_path(start: int, succ: int) -> List[int]:\n", + " \"\"\"Walk from start to succ, recording new nodes until a branching node is hit.\"\"\"\n", " path = [start, succ]\n", " visited.add((start, succ))\n", " \n", " while G.degree(succ) == 2:\n", " next_node = next(n for n in G.neighbors(succ) if n != path[-2])\n", "\n", - " if in_visited(succ, next_node) or is_branchpoint_or_tip(succ):\n", + " if was_visited(succ, next_node) or is_branchpoint_or_tip(succ):\n", " break\n", " \n", " path.append(next_node)\n", @@ -439,18 +972,19 @@ " elif is_branchpoint_or_tip(node):\n", " branchpoints.add(node)\n", " for succ in G.neighbors(node):\n", - " if not in_visited(node, succ):\n", + " if not was_visited(node, succ):\n", " branches.append(walk_path(node, succ))\n", " \n", " # split branches\n", - " split_edges = []\n", " if not ignore_swc_tracing_interruptions: # TODO: fix!\n", - " split_edges += _find_swc_tracing_interruptions(tree)\n", + " split_edges = _find_swc_tracing_interruptions(tree)\n", + " branches = _split_branches(branches, split_edges)\n", + " branchpoints.update(set(p for (p,n) in split_edges))\n", + " \n", " # TODO: add max_len\n", - " # if max_len is not None:\n", + " if max_len is not None:\n", + " raise NotImplementedError(\"max_len not implemented\")\n", "\n", - " branches = _split_branches(branches, split_edges)\n", - " branchpoints.update(set(p for (p,n) in split_edges))\n", "\n", " if return_branchpoints:\n", " branchpoint_edges = sum([list(G.edges(n)) for n in branchpoints], [])\n", @@ -481,7 +1015,7 @@ " tree.node_attrs[n].update(missing_attrs)\n", " return tree\n", "\n", - "def compartmentalize(tree: MorphTree, ncomp: int = 1, min_radius: Optional[float] = None, max_len: Optional[float] = None, ignore_swc_tracing_interruptions: bool = True, relevant_type_ids: Optional[List[int]] = None) -> MorphTree:\n", + "def compartmentalize(tree: MorphTree, ncomp: int = 1, min_radius: Optional[float] = None, max_len: Optional[float] = None, ignore_swc_tracing_interruptions: bool = True, relevant_type_ids: Optional[List[int]] = [1,2,3,4]) -> MorphTree:\n", " \"\"\"Return a networkX graph that indicates the compartment structure.\n", "\n", " Build a new graph made up of compartments in every branch. These compartments are\n", @@ -528,7 +1062,7 @@ " \"\"\"\n", " tree = _add_missing_swc_attrs(tree)\n", "\n", - " branches = list_branches(tree)\n", + " branches = list_branches(tree, ignore_swc_tracing_interruptions=ignore_swc_tracing_interruptions, max_len=max_len, relevant_ids=relevant_type_ids)\n", " nodes_df = tree.to_pandas()[0].astype(float)\n", "\n", " # create new set of indices which arent already used as node indices to label comps\n", @@ -536,10 +1070,8 @@ " num_new_inds = len(branches)*ncomp\n", " proposed_inds = set(range(num_new_inds + len(existing_inds)))\n", " proposed_comp_inds = list(proposed_inds - existing_inds) # avoid overlap w. node indices\n", - " \n", - " v_interp = vmap(jnp.interp, in_axes=(None, None, 1), out_axes=1)\n", - " \n", - " # identify tip nodes (degree == 1)\n", + " \n", + " # identify tip nodes (degree == 1 -> node appears only once in edges)\n", " nodes_in_edges, node_counts_in_edges = np.unique(tree.edges, return_counts=True)\n", " tip_node_inds = nodes_in_edges[node_counts_in_edges == 1]\n", "\n", @@ -551,9 +1083,8 @@ " xyzr_i = node_attrs[[\"x\", \"y\", \"z\", \"r\"]]\n", " xyzr.append(xyzr_i.values)\n", "\n", - " xyz_i = xyzr_i[[\"x\", \"y\", \"z\"]]\n", - " edge_lens = ((xyz_i.diff(axis=0).fillna(0)**2).sum(axis=1)**.5)\n", - " # TODO: handle nans\n", + " compute_edge_lens = lambda x: (x.diff(axis=0).fillna(0)**2).sum(axis=1)**.5\n", + " edge_lens = compute_edge_lens(xyzr_i[[\"x\", \"y\", \"z\"]])\n", " node_attrs[\"l\"] = edge_lens.cumsum() # path length\n", " \n", " # For single-point somatata, we set l = 2*r this ensures\n", @@ -563,7 +1094,7 @@ " radius = node_attrs[\"r\"].iloc[0]\n", " node_attrs[\"l\"] = np.array([0, 2*radius])\n", "\n", - " branch_id = node_attrs[\"id\"].iloc[-1] # TODO: handle multi ids within branch!\n", + " branch_id = node_attrs[\"id\"].iloc[-1] # TODO: better handle mult. ids in branch!\n", " branch_len = max(node_attrs[\"l\"])\n", " comp_len = branch_len / ncomp\n", " comp_locs = list(np.linspace(comp_len/2, branch_len - comp_len/2, ncomp))\n", @@ -595,12 +1126,14 @@ " branch_edges.append(list(zip(comp_attrs[:-1, 0], comp_attrs[1:, 0])))\n", " branch_nodes.append(comp_attrs)\n", "\n", - " branch_nodes = jnp.concatenate(branch_nodes)\n", + " branch_nodes = np.concatenate(branch_nodes)\n", " comp_attrs_keys = [\"idx\", \"branch\", \"branchpoint\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", + " \n", " int_cols = [\"idx\", \"branch\", \"id\"]\n", - " bool_cols = [\"branchpoint\"]\n", " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", + " \n", + " bool_cols = [\"branchpoint\"]\n", " comp_df[bool_cols] = comp_df[bool_cols].astype(bool)\n", "\n", " # threshold radius\n", @@ -610,13 +1143,13 @@ " # drop duplicated branch nodes\n", " comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", " comp_df = comp_df.set_index(\"idx\")\n", - "\n", " comp_attrs = comp_df.to_dict(orient=\"index\")\n", + "\n", + " # create comp edges\n", " comp_edges = sum(branch_edges, [])\n", " comp_edge_attrs = {(i,j): {\"comp_edge\": True, \"synapse\": False} for i,j in comp_edges}\n", "\n", - " global_attrs = {\"xyzr\": xyzr} # TODO: rm xyzr from Module? only used for plotting\n", - " comp_tree = MorphTree(comp_attrs, comp_edge_attrs, global_attrs)\n", + " comp_tree = MorphTree(comp_attrs, comp_edge_attrs, {\"xyzr\": xyzr})\n", " comp_tree = comp_tree.reindex_nodes(dict(zip(comp_df.index, range(len(comp_df)))))\n", " return comp_tree\n", "\n", @@ -625,16 +1158,20 @@ "\n", " Makes the imported and compartmentalized morphology compatible with jaxley.\n", " \"\"\"\n", - "\n", - " group_ids = {0: \"undefined\", 1: \"soma\", 2: \"axon\", 3: \"basal\", 4: \"apical\"}\n", - "\n", " nodes_df, edge_df, global_attrs = tree.to_pandas()\n", - " global_attrs = pd.concat([global_attrs, pd.Series({\"channels\": {}, \"synapses\": {}})])\n", + " module_global_attrs = pd.Series({\"channels\": {}, \"synapses\": {}, \"group_names\": []})\n", + " global_attrs = pd.concat([global_attrs, module_global_attrs])\n", " \n", " # rename/reformat existing columns\n", - " nodes_df[\"groups\"] = nodes_df[\"id\"].apply(lambda x: [group_ids[x]])\n", + " group_ids = {0: \"undefined\", 1: \"soma\", 2: \"axon\", 3: \"basal\", 4: \"apical\"}\n", + " for group_id, group_name in group_ids.items():\n", + " where_group = nodes_df[\"id\"] == group_id\n", + " if where_group.any():\n", + " global_attrs[\"group_names\"].append(group_name)\n", + " nodes_df[group_name] = where_group\n", " nodes_df = nodes_df.drop(columns=[\"id\"])\n", - " nodes_df = nodes_df.rename({\"r\": \"radius\", \"l\": \"length\", \"branch\": \"branch_index\"}, axis=1)\n", + " module_col_names = {\"r\": \"radius\", \"l\": \"length\", \"branch\": \"branch_index\"}\n", + " nodes_df = nodes_df.rename(module_col_names, axis=1)\n", "\n", " # new columns\n", " nodes_df[\"capacitance\"] = 1.0\n", @@ -697,7 +1234,7 @@ " acc_parents.append([-1] + parents.tolist())\n", " return acc_parents\n", "\n", - "def _build_module(morph_comps: MorphTree) -> Module:\n", + "def _build_module(morph_comps: MorphTree) -> jx.Module:\n", " \"\"\"Build a Module from a compartmentalized morphology.\n", "\n", " This function builds a Module from a MorphTree.\n", @@ -709,21 +1246,15 @@ " The Module built from the MorphTree.\n", " \"\"\"\n", " node_df, edge_df, global_attrs = morph_comps.to_pandas()\n", - " acc_parents = _compute_branch_parents(node_df, edge_df)\n", "\n", " nodes_per_branch = node_df[\"branch_index\"].value_counts()\n", - " assert nodes_per_branch.nunique() == 1, (\n", - " \"`from_graph()` does not support a varying number of compartments in each \"\n", - " \"branch.\"\n", - " )\n", + " assert nodes_per_branch.nunique() == 1, (\"`from_graph()` does not support a varying number of compartments in each branch.\")\n", + " \n", + " # TODO: MorphTree backend: read the MorphTree straight into the Module\n", + " acc_parents = _compute_branch_parents(node_df, edge_df)\n", " module = _build_module_scaffold(node_df, parent_branches=acc_parents, xyzr=global_attrs[\"xyzr\"])\n", - " # TODO: MorphTree backend, it should be possible to the MorphTree into the Module\n", "\n", - " groups_df = node_df.groups.explode()\n", - " groups = groups_df.groupby(groups_df).groups\n", - " for group_name, group_inds in groups.items():\n", - " module.select(nodes=group_inds).add_to_group(group_name)\n", - " node_df.drop(columns=[\"groups\"], inplace=True)\n", + " # TODO: add groups\n", "\n", " node_df.columns = [\n", " \"global_\" + col if \"local\" not in col and \"index\" in col else col\n", @@ -741,46 +1272,708 @@ " module.channels = global_attrs[\"channels\"]\n", " module.membrane_current_names = [c.current_name for c in module.channels]\n", " module.synapse_names = [s._name for s in module.synapses]\n", + " \n", " return module" ] }, { "cell_type": "code", - "execution_count": 444, + "execution_count": 114, "metadata": {}, "outputs": [], "source": [ - "morph_tree = swc_to_morphtree(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", - "morph_comps = compartmentalize(morph_tree, ncomp=1)\n", - "morph_comps = _add_jaxley_meta_data(morph_comps)\n", - "morph_comps = _replace_branchpoints_with_edges(morph_comps)\n", - "cell = _build_module(morph_comps)" + "# G = morph_tree.to_nx()\n", + "# branches = list_branches(morph_tree)\n", + "\n", + "# min_len = 1e-5\n", + "# max_len = 100\n", + "# xyz = lambda i: np.array([G.nodes[i][k] for k in [\"x\", \"y\", \"z\"]])\n", + "# dl = lambda i,j: np.sqrt(((xyz(i) - xyz(j)) ** 2).sum())\n", + "\n", + "# for branch in branches:\n", + "# edge_lens = np.array([dl(i,j) for i,j in zip(branch[:-1], branch[1:])])\n", + "# edge_lens = np.where(edge_lens < min_len, min_len, edge_lens)\n", + "# cum_edge_lens = np.concatenate([[0], edge_lens.cumsum()])\n", + "# local_branch_inds = cum_edge_lens // max_len\n", + " \n", + "# # Find indices where local_branch_inds changes\n", + "# change_points = np.where(np.diff(local_branch_inds) != 0)[0]\n", + "# # Get the edges (pairs of nodes) where the change occurs\n", + "# change_edges = [(branch[i], branch[i+1]) for i in change_points]\n", + "# print(change_edges)\n", + " \n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 168, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "morph_tree = swc_to_morphtree(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", + "morph_comps = compartmentalize(morph_tree, ncomp=1)\n", + "morph_comps = _add_jaxley_meta_data(morph_comps)\n", + "morph_comps = _replace_branchpoints_with_edges(morph_comps)\n", + "cell = _build_module(morph_comps)" + ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 171, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "for n, attrs in morph_comps.node_attrs.items():\n", + " attrs[\"test\"] = jnp.ones((1,1))" + ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 180, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "data": { + "text/plain": [ + "{'apical': Array([ True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, False, True, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True], dtype=bool),\n", + " 'axial_resistivity': Array([1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", + " 1000., 1000.], dtype=float64),\n", + " 'basal': Array([False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, True, True,\n", + " True, True, True, True, True, True, True, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False], dtype=bool),\n", + " 'branch_index': Array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n", + " 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n", + " 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\n", + " 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n", + " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,\n", + " 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,\n", + " 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n", + " 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,\n", + " 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,\n", + " 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\n", + " 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,\n", + " 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154], dtype=int64),\n", + " 'capacitance': Array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", + " 1., 1.], dtype=float64),\n", + " 'cell_index': Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0], dtype=int64),\n", + " 'comp_index': Array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n", + " 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n", + " 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\n", + " 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n", + " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,\n", + " 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,\n", + " 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n", + " 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,\n", + " 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,\n", + " 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\n", + " 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,\n", + " 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154], dtype=int64),\n", + " 'length': Array([2.44227045e+02, 4.27393845e+00, 2.40982169e+02, 4.67513057e+01,\n", + " 8.65335301e+01, 1.71028475e+01, 2.46046913e+01, 5.00520562e+01,\n", + " 5.37613212e+01, 1.59714426e+02, 7.48997041e+01, 1.86023601e+01,\n", + " 1.17733295e+02, 3.48567067e+00, 6.99059144e+01, 4.18909298e+00,\n", + " 1.13682833e+02, 1.63440324e+01, 8.36221267e+01, 7.14833481e+01,\n", + " 5.60078230e+01, 8.65139844e+00, 1.19434577e+01, 1.18341624e+01,\n", + " 6.04821169e+01, 2.22652195e+00, 8.64983664e+01, 1.01865650e+02,\n", + " 1.04995175e+02, 1.81920197e+02, 1.14303517e+02, 1.24831143e+01,\n", + " 8.32100003e+00, 5.84467372e+01, 6.03573930e+01, 7.07951637e+00,\n", + " 7.97070260e+00, 6.54202812e+01, 3.98980463e+01, 4.73884329e+01,\n", + " 1.11205690e+01, 1.58199233e+01, 1.06745317e+01, 1.93803826e+02,\n", + " 4.68279814e+01, 1.16410913e+02, 2.18482129e+01, 3.98674512e+01,\n", + " 1.31019920e+01, 1.14727338e+02, 2.62038740e+01, 2.36348559e+01,\n", + " 1.46372243e+02, 1.77078541e+02, 1.51908215e+02, 1.88632174e+01,\n", + " 1.99484663e+01, 2.01271439e+02, 9.98779052e+01, 7.20884214e+01,\n", + " 1.03907121e+02, 3.36359252e+01, 5.89085479e+01, 1.07287479e+02,\n", + " 7.34204122e+01, 2.08664292e+01, 6.14484518e+01, 7.76717167e+00,\n", + " 3.75958736e+01, 5.98194156e+00, 8.28050749e+01, 5.15007803e+01,\n", + " 7.69670339e+01, 1.38513551e+02, 5.89333860e-01, 7.13845088e+01,\n", + " 2.47290064e+02, 1.03945877e+01, 1.37263347e+02, 2.07062881e+02,\n", + " 8.30791299e+01, 1.37880444e+01, 2.48048336e+01, 2.33607253e+01,\n", + " 1.74379156e+01, 5.70210922e+01, 5.34781853e+01, 7.01609823e+01,\n", + " 1.41706274e+02, 1.99370310e+02, 2.27512040e+02, 1.94238703e+02,\n", + " 5.71602082e+01, 2.87768195e+01, 9.24722613e+01, 2.51768663e+00,\n", + " 8.65304227e+01, 1.82482876e-01, 3.18533866e+01, 6.42759470e+01,\n", + " 1.39461130e+01, 4.02934985e+01, 7.98859607e+01, 1.59913083e+02,\n", + " 2.82131445e+01, 1.00706363e+02, 4.29941742e+01, 2.31970368e+02,\n", + " 5.13527546e+01, 1.50636642e+01, 6.75241154e+01, 6.61563113e+01,\n", + " 1.26906107e+01, 1.76133011e+02, 4.50523713e+01, 2.06259293e+02,\n", + " 1.87169885e+01, 1.47306550e+01, 3.54588338e+01, 1.75242344e+02,\n", + " 1.32771667e+00, 1.29183383e+02, 5.74656307e-01, 1.40209297e+02,\n", + " 1.78636825e+01, 7.75760254e+01, 5.89367355e+01, 1.18174494e+02,\n", + " 7.61007831e+01, 6.06704256e+01, 9.94571441e+01, 9.31158162e+01,\n", + " 1.92990563e+02, 8.83708697e+01, 1.56182708e+02, 2.01756276e+01,\n", + " 4.55395873e+01, 3.14180157e+02, 4.96918789e+01, 1.46905134e+02,\n", + " 1.03873063e+02, 1.42322205e+02, 3.09882545e+01, 3.72726316e+01,\n", + " 6.08114959e+01, 2.70516732e+01, 6.01662185e+01, 8.38092975e+01,\n", + " 4.53456511e+01, 2.19301346e+02, 2.05210304e+02, 9.17689802e+01,\n", + " 7.76761757e+00, 1.27914756e+02, 1.22357698e+02], dtype=float64),\n", + " 'radius': Array([0.24 , 0.4 , 0.24 , 0.4 , 0.24 ,\n", + " 0.4 , 0.24 , 0.4 , 0.24 , 0.57828469,\n", + " 0.24 , 0.79 , 0.4 , 0.87 , 0.24 ,\n", + " 0.87 , 0.24 , 0.87 , 0.24 , 0.87 ,\n", + " 0.4 , 1.10211933, 0.72973568, 1.18 , 0.4 ,\n", + " 1.18 , 0.4 , 1.03 , 0.4 , 1.5 ,\n", + " 0.46888305, 6.36039227, 7.96 , 0.71 , 1.10336459,\n", + " 1.18544992, 0.79 , 0.55 , 0.55 , 0.55 ,\n", + " 0.55 , 0.55 , 0.55 , 0.24 , 0.55 ,\n", + " 0.24 , 0.55 , 0.87 , 0.55 , 0.4 ,\n", + " 0.67599993, 0.55 , 0.55 , 0.4 , 0.24 ,\n", + " 0.55 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", + " 0.4 , 0.4 , 0.4 , 0.4 , 0.24 ,\n", + " 0.55 , 0.4 , 0.55 , 0.55 , 0.55 ,\n", + " 0.55 , 0.55 , 0.475 , 0.4 , 0.55 ,\n", + " 0.87 , 0.4 , 1.34 , 0.43771301, 0.4 ,\n", + " 0.4 , 0.4 , 0.4 , 1.03 , 0.475 ,\n", + " 0.55 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", + " 0.4 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", + " 0.87 , 0.4 , 0.87 , 0.4 , 0.24 ,\n", + " 0.55 , 0.24 , 0.24 , 0.24 , 0.24 ,\n", + " 0.24 , 0.24 , 0.4 , 0.4 , 0.31876093,\n", + " 0.4 , 0.24 , 0.24 , 0.4 , 0.24 ,\n", + " 0.4 , 0.41539049, 0.42840312, 0.4 , 0.4 ,\n", + " 0.4 , 0.4 , 0.4 , 0.24 , 0.24 ,\n", + " 0.24 , 0.24 , 0.24 , 0.24 , 0.4 ,\n", + " 0.4 , 1.18 , 0.55 , 0.55 , 0.4 ,\n", + " 0.4 , 0.4 , 0.24 , 0.4 , 0.4 ,\n", + " 0.24 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", + " 0.4 , 0.24 , 0.24 , 0.24 , 0.24 ,\n", + " 0.24 , 0.24 , 0.24 , 0.24 , 0.4 ], dtype=float64),\n", + " 'soma': Array([False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, True, False, True, True, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False, False, False, False, False, False, False, False,\n", + " False, False], dtype=bool),\n", + " 'test': Array([[[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]],\n", + " \n", + " [[1.]]], dtype=float64),\n", + " 'v': Array([-70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", + " -70.], dtype=float64),\n", + " 'x': Array([-3.88140591e+01, -3.47665895e+01, -4.62851460e+01, -2.86055828e+01,\n", + " -6.04664941e+01, -2.22141373e+01, -2.17649065e+01, -1.46674384e+01,\n", + " -2.65934838e+01, -7.64561829e+00, -5.55926798e+00, -2.19500000e+00,\n", + " -1.62525338e+01, -4.50000000e-02, -8.90751403e+00, 4.35000000e-01,\n", + " 7.77627645e+00, -7.36059522e-01, -1.65841611e+01, 8.14565057e-01,\n", + " 2.13285961e+01, 6.89445123e+00, 4.05295155e+00, 7.38500000e+00,\n", + " 1.67828190e+01, 7.71000000e+00, 2.01344625e+00, 1.08146263e+01,\n", + " 2.52294648e+00, 1.77869711e+01, 2.53586342e+01, 1.96899895e+00,\n", + " -1.43191395e+00, 1.07794505e+01, -3.38124350e+00, -1.10783510e+01,\n", + " -1.35700000e+01, -2.17445329e+01, -2.04646257e+01, -2.40601176e+01,\n", + " -2.73733044e+01, -3.17616719e+01, -3.12286604e+01, -3.46899208e+01,\n", + " -4.09685246e+01, -4.65120057e+01, -3.84031315e+01, -1.34834327e+01,\n", + " -1.73996943e+01, -2.91027177e+01, -1.28358122e+01, -1.45804066e+01,\n", + " -1.11253485e+01, -8.15036285e+00, -2.21252519e+01, -2.70002952e+01,\n", + " -2.46579547e+01, -6.35780453e+01, -4.48365602e+01, -3.92184464e+01,\n", + " -7.13437925e+01, -5.51445682e+01, -6.44816671e+01, -9.35387104e+01,\n", + " -6.91735810e+01, 1.03711686e+01, 1.74618476e+01, 5.43191123e+00,\n", + " 1.19414126e+01, 2.84773808e+00, 1.93901408e+00, 1.93595787e-01,\n", + " 1.29500000e+00, -2.72412240e+01, -5.80263563e+00, 1.46500000e+00,\n", + " 2.22187553e+01, 2.53570369e+00, -1.84266862e+00, 1.51830631e+01,\n", + " 2.20613544e+01, -3.84324259e+00, 1.71926423e+00, -5.57872256e-01,\n", + " -7.05500000e+00, -1.55119060e+01, -4.13728233e+00, -3.67836032e+01,\n", + " -6.20384343e+01, 1.05045409e+01, -2.26490914e+01, 1.32178956e+01,\n", + " 7.66484909e+00, 2.31079088e+01, 1.61021887e+01, 1.46392832e+01,\n", + " 1.10439022e+01, 1.58050000e+01, 1.78764087e+01, 2.12141509e+01,\n", + " 1.89122741e+01, 2.25274810e+01, 3.25100849e+01, 2.20398342e+01,\n", + " 1.89171231e+01, 5.45815165e+01, 5.40631551e+01, 8.34180477e+01,\n", + " 2.02817763e+01, 1.98801349e+01, 1.25974545e+01, 2.77192419e+01,\n", + " 2.20200000e+01, 2.96250976e+01, 3.23790033e+01, 5.64145841e+01,\n", + " 2.72277182e+01, 2.94151398e+01, 2.78960365e+01, 6.50720438e+01,\n", + " 3.15165333e+01, 5.63451453e+01, 3.10089173e+01, 1.77797413e+01,\n", + " 1.11620758e+01, 9.16106710e+00, 9.64909680e+00, 1.29319048e+01,\n", + " -5.55020829e+00, 2.96935061e+01, 2.25534511e+01, 5.56528605e+01,\n", + " 9.99225200e+01, 6.09454728e+01, 2.10102712e+01, 2.17317292e+01,\n", + " 2.82162141e+01, 7.31353939e+01, 4.62060688e+01, 9.44369001e+01,\n", + " 9.65242301e+01, -1.17380615e+01, -9.09180601e+00, -4.08751305e+00,\n", + " -1.72995328e+01, -3.10644853e+01, -4.28129473e+01, 6.47747363e+01,\n", + " 4.36760765e+01, 4.51429852e+01, 2.91750433e+01, -2.49549155e+01,\n", + " -1.26787102e+01, 1.20463251e+01, -7.37012198e+00], dtype=float64),\n", + " 'y': Array([-467.22175756, -399.80279422, -486.5345792 , -387.37532949,\n", + " -414.1453725 , -372.96551637, -377.3156131 , -353.98109982,\n", + " -376.98191136, -303.34552605, -358.39305046, -261.665 ,\n", + " -285.39362573, -254.215 , -266.40405108, -252.16 ,\n", + " -281.71696586, -244.85748401, -260.2859902 , -214.87275928,\n", + " -232.50102171, -183.59455434, -184.05942731, -181.41 ,\n", + " -194.19403766, -179.465 , -192.55559887, -152.12482716,\n", + " -159.71766977, -77.08047503, -135.40164775, -5.83329182,\n", + " 3.88615594, 7.08749238, 8.8679957 , 12.04773412,\n", + " 13.225 , 12.61433384, 25.35064568, 58.31648265,\n", + " 45.93333923, 51.6311146 , 53.87829662, 72.59061764,\n", + " 67.5258203 , 90.24287678, 62.48958086, 17.41335817,\n", + " 16.59322005, 30.47593334, 18.89287553, 25.87304953,\n", + " 34.73637081, 46.83288325, 71.8043282 , 27.79545894,\n", + " 19.7320453 , 106.42462676, 63.67345983, 28.461845 ,\n", + " 13.60008591, 60.41825342, 51.51458261, 103.55194279,\n", + " 97.88617877, 11.693338 , 5.92279773, 11.2442272 ,\n", + " 13.02718082, 13.8047606 , 36.66509591, 21.27139234,\n", + " 13.865 , 82.42212564, 37.49542511, 13.58 ,\n", + " 16.19182246, 13.55030688, 14.24151464, 65.01517003,\n", + " 28.39995684, 24.25018969, 30.79639145, 14.44969604,\n", + " 21.1 , 25.70793736, 38.95245081, 43.61421049,\n", + " 56.63902138, 104.13980011, 128.72752265, 61.24197344,\n", + " 56.74388898, 80.96430726, 100.16385372, 17.57025633,\n", + " 37.5829197 , 17.47 , 19.03547843, 22.4971067 ,\n", + " 17.6838308 , 38.1357177 , 43.22117954, 65.74640932,\n", + " 47.65934149, 71.65161919, 50.48598164, 56.32578249,\n", + " 34.38530483, 54.39253945, 76.57172314, 68.73963285,\n", + " 61.15 , 129.01740518, 80.26277401, 76.98769888,\n", + " 31.4711477 , 44.24275793, 51.97663607, 114.39658219,\n", + " 51.13726417, 121.04355091, 66.35524526, 114.98295441,\n", + " 80.27069362, 108.96831315, 96.68302983, 151.95575124,\n", + " 127.09725403, -2.67126416, 9.57396065, 1.81999783,\n", + " 41.86340217, -208.54174156, -130.79601473, -223.35724107,\n", + " -219.61857652, -327.27298222, -235.51987584, -285.77979536,\n", + " -265.36770569, -209.22123097, -188.67837147, -186.40151314,\n", + " -208.19400105, -238.99450251, -223.94711117, -218.78824582,\n", + " -216.75015638, -461.63075952, -467.24896436, -530.30717898,\n", + " -521.40277554, -433.83064446, -437.11824757], dtype=float64),\n", + " 'z': Array([ 61.14692632, 12.19748436, 27.28 , 25.76 ,\n", + " 11.51407401, 17.97892053, 13.97488458, 9.6433186 ,\n", + " -4.4 , 5.27622108, -4.67527252, 0.76 ,\n", + " 28.87 , 8.565 , -11.25195396, 11.77 ,\n", + " 34.33086009, 8.37256587, 43.27 , -2.23751834,\n", + " 15.07087261, 4.44270864, 6.41105726, 14.395 ,\n", + " 29.76343097, 19.835 , 30.60567925, 5.06034567,\n", + " 35.99978727, 1.84 , 44.08334803, 0. ,\n", + " 0. , 17.28816403, 30.10524862, 58.25343038,\n", + " 51.36 , 48.43476897, 56.67776162, 62.79 ,\n", + " 53.24066087, 60.93608537, 55.97186959, 35.18036425,\n", + " 58.73176729, 53.04 , 57.68 , 41.53315306,\n", + " 53.36 , 26.39211569, 34.5980048 , 31.59748853,\n", + " 25.0789444 , -32.10959913, 17.94486003, 53.10575416,\n", + " 49.45136379, 50.12462076, 31.64510844, 39.82193807,\n", + " 41.37762411, 47.0270826 , 61.04 , 38.71177192,\n", + " 43.42675924, 46.82048985, 37.3824518 , 37.78761858,\n", + " 20.64790945, 42.47678577, 31.10010505, 24.42659665,\n", + " 6.635 , 38.91897803, 12.56 , 3.84 ,\n", + " 19.38012979, 44.71551285, -28.97702095, 53.88555438,\n", + " 46.94412938, 30.79487086, 17.68 , 21.03781985,\n", + " 33.54 , 23.16780124, 23.12 , 14.8 ,\n", + " 22.79895063, 17.89706698, 54.31 , -22.33046626,\n", + " 24.56167616, 8.23 , 5.59 , 26.23 ,\n", + " 30.63 , 26.23 , 41.29887915, 17.00837525,\n", + " 31.40269374, 13.69093954, 29.31746084, 19.04132129,\n", + " 24.5473551 , 25.04 , 15.84 , 10.179687 ,\n", + " 21.76 , 15.44924698, 10.58139591, 18.15 ,\n", + " 15.68 , 5.72997792, 0.91787377, 53.70443838,\n", + " 50.42479344, 54.85576002, 49.55335055, 59.06966685,\n", + " 56.33915476, 58.88 , 56.56 , 34.01003695,\n", + " 30.71 , 58.7655592 , 20.02441116, 15.76 ,\n", + " 16.30609289, 15.59233597, 40.87062569, 39.75 ,\n", + " 33.77031441, 38.62313788, 4.15 , 45.45387938,\n", + " 48.05727869, 39.06053515, 34.91626415, 22.92708681,\n", + " 40.99827221, 36.08 , 20.57528003, 40.79519918,\n", + " 45.52 , 42.24970713, 29.64160623, 36.28412232,\n", + " 37.63106542, 1.95884902, -2.28342966, 26.3779279 ,\n", + " 51.27 , 0.15 , 34.47 ], dtype=float64)}" + ] + }, + "execution_count": 180, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "jax.tree_util.tree_map(lambda *args: jnp.array(args), *morph_comps.node_attrs.values())" + ] }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 117, "metadata": {}, "outputs": [], "source": [ @@ -882,6 +2075,26 @@ " " ] }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": {}, + "outputs": [], + "source": [ + "tree_insert(morph_comps, [0, 2], DummyChannel(\"test1\"))\n", + "tree_insert(morph_comps, [0, 2], DummyChannel(\"test2\"))\n", + "\n", + "tree_connect(morph_comps, [0, 1], [3, 2], DummySynapse(\"test1\"))\n", + "tree_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test2\"))\n", + "\n", + "# tree_set(morph_comps, \"gbar_test1\", 123)\n", + "# tree_set(morph_comps, \"gbar_test2\", 123)\n", + "\n", + "# subtree = tree_view(morph_comps, list(range(0,2)))\n", + "# subtree = tree_set(subtree, \"length\", 99.99) # <-- setting on views works\n", + "# morph_comps = merge_trees([morph_comps, subtree])" + ] + }, { "cell_type": "code", "execution_count": 356, @@ -911,26 +2124,6 @@ "morph_comps = _add_meta_data(morph_comps)" ] }, - { - "cell_type": "code", - "execution_count": 222, - "metadata": {}, - "outputs": [], - "source": [ - "tree_insert(morph_comps, [0, 2], DummyChannel(\"test1\"))\n", - "tree_insert(morph_comps, [0, 2], DummyChannel(\"test2\"))\n", - "\n", - "tree_connect(morph_comps, [0, 1], [3, 2], DummySynapse(\"test1\"))\n", - "tree_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test2\"))\n", - "\n", - "tree_set(morph_comps, \"gbar_test1\", 123)\n", - "tree_set(morph_comps, \"gbar_test2\", 123)\n", - "\n", - "subtree = tree_view(morph_comps, list(range(0,2)))\n", - "subtree = tree_set(subtree, \"length\", 99.99) # <-- setting on views works\n", - "morph_comps = merge_trees([morph_comps, subtree])" - ] - }, { "cell_type": "code", "execution_count": 244, @@ -1119,6 +2312,39 @@ "# plt.tight_layout()\n", "# plt.show()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Simple and elegant solution using tree_map\n", + "inner_trees = list(morph_comps.node_attrs.values())\n", + "jax_node_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *inner_trees)\n", + "\n", + "print(\"Original structure (first few nodes):\")\n", + "for i, (k, v) in enumerate(morph_comps.node_attrs.items()):\n", + " print(f\"Node {k}: {v}\")\n", + " if i >= 2:\n", + " break\n", + "\n", + "print(f\"\\nTransformed to arrays:\")\n", + "for attr, values in jax_node_attrs.items():\n", + " if hasattr(values, 'shape'):\n", + " print(f\"{attr}: {type(values).__name__} with shape {values.shape}\")\n", + " else:\n", + " print(f\"{attr}: {type(values).__name__} with length {len(values)}\")\n", + "\n", + "print(f\"\\nSample values:\")\n", + "for attr, values in jax_node_attrs.items():\n", + " if hasattr(values, 'shape'):\n", + " print(f\"{attr}: {values[:3]}\") # Show first 3 values\n", + " else:\n", + " print(f\"{attr}: {values[:3]}\") # Show first 3 values\n", + " if len(jax_node_attrs) > 10: # Don't print too many\n", + " break\n" + ] } ], "metadata": { From b77dffb158678d190174df66386db87f55b928fa Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Tue, 10 Jun 2025 15:31:43 +0200 Subject: [PATCH 19/24] wip: improved interpolation --- dev.ipynb | 815 +++++++++++++----------------------------------------- 1 file changed, 185 insertions(+), 630 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index d8fe30e22..ff7a65e33 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 7, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -49,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -222,13 +222,13 @@ "# utility functions\n", "# -----------------\n", "\n", - "def compute_xyz(tree: MorphTree, length: float = 1.0, spread: float = np.pi/8, spread_decay: float = 0.9, twist: float = 0.0, xy_only: bool = True) -> dict[int, tuple[float, float, float]]:\n", - " \"\"\"Compute xyz coordinates for a tree-like appearance of a MorphTree graph in 2D or 3D.\n", + "def compute_xyz(G: nx.DiGraph, length: float = 1.0, spread: float = np.pi/8, spread_decay: float = 0.9, twist: float = 0.0, xy_only: bool = True) -> dict[int, tuple[float, float, float]]:\n", + " \"\"\"Compute xyz coordinates for a tree-like appearance of a networkX graph in 2D or 3D.\n", " \n", " Handles branches implicitly since nodes in a branch have 1 child.\n", "\n", " Args:\n", - " tree: The MorphTree to compute node xyz coordinates for.\n", + " G: The Graph to compute node xyz coordinates for.\n", " length: The length of each edge.\n", " spread: The opening angle at which the edges spread out.\n", " spread_decay: Multiplicative decay factor for the opening angle / spread.\n", @@ -239,7 +239,6 @@ " A dictionary mapping node indices to xyz coordinates.\n", " \"\"\"\n", " # TODO: Replace compute_xyz with this or vice versa, redundant!\n", - " G = tree.to_nx()\n", " root = next(n for n, d in G.in_degree() if d == 0)\n", " pos = {root: (0.0, 0.0, 0.0)}\n", "\n", @@ -268,70 +267,67 @@ " recurse(child, depth + 1, th, ph)\n", "\n", " recurse(root, theta=0.0, phi=np.pi/2)\n", - " return pos\n", - "\n", - "v_interp = vmap(jnp.interp, in_axes=(None, None, 1), out_axes=1)" + " return pos" ] }, { "cell_type": "code", - "execution_count": 303, + "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "def pandas_to_nx(\n", - " node_attrs: pd.DataFrame,\n", - " edge_attrs: pd.DataFrame,\n", - " global_attrs: pd.Series\n", + " node_attrs: pd.DataFrame, edge_attrs: pd.DataFrame, global_attrs: pd.Series\n", ") -> nx.DiGraph:\n", " \"\"\"Convert node_attrs, edge_attrs and global_attrs from pandas datatypes to a NetworkX DiGraph.\n", - " \n", + "\n", " Args:\n", " node_attrs: DataFrame containing node attributes\n", " edge_attrs: DataFrame containing edge attributes\n", " global_attrs: Series containing global graph attributes\n", - " \n", + "\n", " Returns:\n", " A directed graph with nodes, edges and global attributes from the input data.\n", " \"\"\"\n", " G = nx.from_pandas_edgelist(\n", - " edge_attrs.reset_index(), \n", - " source='level_0', \n", - " target='level_1', \n", + " edge_attrs.reset_index(),\n", + " source=\"level_0\",\n", + " target=\"level_1\",\n", " edge_attr=True,\n", - " create_using=nx.DiGraph()\n", + " create_using=nx.DiGraph(),\n", " )\n", - " \n", - " nx.set_node_attributes(G, node_attrs.to_dict(orient='index'))\n", + "\n", + " nx.set_node_attributes(G, node_attrs.to_dict(orient=\"index\"))\n", " G.graph.update(global_attrs.to_dict())\n", " return G\n", "\n", + "\n", "def nx_to_pandas(G: nx.DiGraph) -> Tuple[pd.DataFrame, pd.DataFrame, pd.Series]:\n", " \"\"\"Convert a NetworkX DiGraph to pandas datatypes.\n", - " \n", + "\n", " Args:\n", " G: Input directed graph\n", - " \n", + "\n", " Returns:\n", " Tuple containing:\n", " - DataFrame of node attributes\n", " - DataFrame of edge attributes\n", " - Series of global graph attributes\n", " \"\"\"\n", - " edge_df = nx.to_pandas_edgelist(G).set_index(['source', 'target'])\n", + " edge_df = nx.to_pandas_edgelist(G).set_index([\"source\", \"target\"])\n", " edge_df.index.names = [None, None]\n", - " node_df = pd.DataFrame.from_dict(dict(G.nodes(data=True)), orient='index')\n", - " \n", + " node_df = pd.DataFrame.from_dict(dict(G.nodes(data=True)), orient=\"index\")\n", + "\n", " return node_df, edge_df, pd.Series(G.graph)\n", "\n", "\n", "def swc_to_nx(fname: str, num_lines: Optional[int] = None) -> nx.DiGraph:\n", " \"\"\"Read a SWC morphology file into a NetworkX DiGraph.\n", - " \n", + "\n", " Args:\n", " fname: Path to the SWC file\n", " num_lines: Number of lines to read from the file\n", - " \n", + "\n", " Returns:\n", " A directed graph representing the morphology where:\n", " - Nodes have attributes: id, x, y, z, r (radius)\n", @@ -340,13 +336,16 @@ " i_id_xyzr_p = np.loadtxt(fname)[:num_lines]\n", "\n", " graph = nx.DiGraph()\n", - " for i, id, x, y, z, r, p in i_id_xyzr_p.tolist(): # tolist: np.float64 -> float\n", + " for i, id, x, y, z, r, p in i_id_xyzr_p.tolist(): # tolist: np.float64 -> float\n", " graph.add_node(int(i), **{\"id\": int(id), \"x\": x, \"y\": y, \"z\": z, \"r\": r})\n", " if p != -1:\n", " graph.add_edge(int(p), int(i))\n", " return graph\n", "\n", - "def _split_branches(branches: list[list[int]], split_edges: list[tuple[int, int]]) -> list[list[int]]:\n", + "\n", + "def _split_branches(\n", + " branches: list[list[int]], split_edges: list[tuple[int, int]]\n", + ") -> list[list[int]]:\n", " \"\"\"Split branches at the given edges.\n", "\n", " Args:\n", @@ -356,20 +355,21 @@ " Returns:\n", " An updated list of branches.\n", " \"\"\"\n", - " for (p, n) in split_edges:\n", + " for p, n in split_edges:\n", " for i, branch in enumerate(branches):\n", " if n in branch:\n", " split_idx = branch.index(n)\n", - " branches[i:i+1] = [branch[:split_idx], branch[split_idx:]]\n", + " branches[i : i + 1] = [branch[:split_idx], branch[split_idx:]]\n", " break\n", " return branches\n", "\n", + "\n", "def _find_swc_tracing_interruptions(G: nx.DiGraph) -> list[tuple[int, int]]:\n", " \"\"\"Identify discontinuities in the swc tracing order.\n", "\n", " Some swc files contain artefacts, where tracing of the same neurite was done\n", - " in disconnected pieces. NEURON swc reader introduce a break in the trace at these \n", - " points, since they parse the file in order. This leads to split branches, which \n", + " in disconnected pieces. NEURON swc reader introduce a break in the trace at these\n", + " points, since they parse the file in order. This leads to split branches, which\n", " should be one. This function identifies these points in the graph.\n", "\n", " Example swc file:\n", @@ -398,12 +398,19 @@ " interrupt_edges = []\n", " for n in G.nodes:\n", " if len(parents := list(G.predecessors(n))) > 0:\n", - " p = parents[0] \n", - " if p != n-1 and degree_is_2(n) and degree_is_2(p):\n", - " interrupt_edges.append((p,n))\n", + " p = parents[0]\n", + " if p != n - 1 and degree_is_2(n) and degree_is_2(p):\n", + " interrupt_edges.append((p, n))\n", " return interrupt_edges\n", "\n", - "def list_branches(G, return_branchpoints: bool = False, ignore_swc_tracing_interruptions=True, relevant_ids: Optional[List[int]] = [1,2,3,4], max_len: Optional[float] = None) -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", + "\n", + "def list_branches(\n", + " G,\n", + " return_branchpoints: bool = False,\n", + " ignore_swc_tracing_interruptions=True,\n", + " relevant_ids: List[int] = [1, 2, 3, 4],\n", + " max_len: Optional[float] = None,\n", + ") -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", " \"\"\"Get all uninterrupted paths in the traced morphology (i.e. branches).\n", "\n", " The graph is traversed depth-first starting from the first found leaf node.\n", @@ -438,16 +445,16 @@ "\n", " def is_branchpoint_or_tip(n: int) -> bool:\n", " if G.degree(n) == 2:\n", - " i,j = G.neighbors(n)\n", - " # trace dir matters here! For segment with node IDs: [1, 1, 2, 2]\n", - " # -> [[1,1], [1,2,2]] \n", - " # <- [[2,2], [2,1,1]] \n", + " i, j = G.neighbors(n)\n", + " # trace dir matters here! For segment with node IDs: [1, 1, 2, 2]\n", + " # -> [[1,1], [1,2,2]]\n", + " # <- [[2,2], [2,1,1]]\n", " return not same_id(n, j)\n", - " \n", + "\n", " is_leaf = G.degree(n) <= 1\n", " is_branching = G.degree(n) > 2\n", " return is_leaf or is_branching\n", - " \n", + "\n", " def same_id(n1: int, n2: int) -> bool:\n", " has_id = lambda n: id_of(n) in relevant_ids if \"id\" in G.nodes[n] else False\n", " if has_id(n1) and has_id(n2):\n", @@ -458,13 +465,13 @@ " \"\"\"Walk from start to succ, recording new nodes until a branching node is hit.\"\"\"\n", " path = [start, succ]\n", " visited.add((start, succ))\n", - " \n", + "\n", " while G.degree(succ) == 2:\n", " next_node = next(n for n in G.neighbors(succ) if n != path[-2])\n", "\n", " if was_visited(succ, next_node) or is_branchpoint_or_tip(succ):\n", " break\n", - " \n", + "\n", " path.append(next_node)\n", " visited.add((succ, next_node))\n", " succ = next_node\n", @@ -482,13 +489,13 @@ " for succ in G.neighbors(node):\n", " if not was_visited(node, succ):\n", " branches.append(walk_path(node, succ))\n", - " \n", + "\n", " # split branches\n", - " if not ignore_swc_tracing_interruptions: # TODO: fix!\n", + " if not ignore_swc_tracing_interruptions: # TODO: fix!\n", " split_edges = _find_swc_tracing_interruptions(G)\n", " branches = _split_branches(branches, split_edges)\n", - " branchpoints.update(set(p for (p,n) in split_edges))\n", - " \n", + " branchpoints.update(set(p for (p, n) in split_edges))\n", + "\n", " # TODO: add max_len\n", " if max_len is not None:\n", " raise NotImplementedError(\"max_len not implemented\")\n", @@ -498,19 +505,20 @@ " return branches, branchpoints, branchpoint_edges\n", " return branches\n", "\n", + "\n", "def _add_missing_swc_attrs(G) -> nx.DiGraph:\n", - " \"\"\"Add missing swc attributes to a MorphTree.\n", + " \"\"\"Add missing swc attributes to a SWC graph.\n", "\n", " Allows to specify morphology from just edges.\n", "\n", " Args:\n", - " tree: The MorphTree to add missing attributes to.\n", + " G: The SWC graph to add missing attributes to.\n", "\n", " Returns:\n", - " The MorphTree with missing attributes set to their defaults.\n", + " The SWC graph with missing attributes set to their defaults.\n", " \"\"\"\n", " defaults = {\"id\": 0, \"r\": 1}\n", - " \n", + "\n", " available_keys = G.nodes[next(iter(G.nodes()))].keys()\n", " xyz = compute_xyz(G) if \"x\" not in available_keys else {}\n", " for n, (x, y, z) in xyz.items():\n", @@ -522,7 +530,15 @@ " nx.set_node_attributes(G, defaults[key], key)\n", " return G\n", "\n", - "def compartmentalize(G: nx.DiGraph, ncomp: int = 1, min_radius: Optional[float] = None, max_len: Optional[float] = None, ignore_swc_tracing_interruptions: bool = True, relevant_type_ids: Optional[List[int]] = [1,2,3,4]) -> MorphTree:\n", + "\n", + "def compartmentalize(\n", + " swc_graph: nx.DiGraph,\n", + " ncomp: int = 1,\n", + " min_radius: Optional[float] = None,\n", + " max_len: Optional[float] = None,\n", + " ignore_swc_tracing_interruptions: bool = True,\n", + " relevant_type_ids: List[int] = [1, 2, 3, 4],\n", + ") -> nx.DiGraph:\n", " \"\"\"Return a networkX graph that indicates the compartment structure.\n", "\n", " Build a new graph made up of compartments in every branch. These compartments are\n", @@ -533,7 +549,7 @@ " o-----------o----------o---o---o---o--------o\n", " o-------x---o----x-----o--xo---o---ox-------o\n", "\n", - " This function returns a MorphTree. The graph is directed only because every\n", + " This function returns a nx:DiGraph. The graph is directed only because every\n", " compartment tracks the xyzr coordinates of the associated SWC file. These xyzr\n", " coordinates are ordered by the order of the traversal of the swc_graph. In later\n", " methods (e.g. build_solve_graph), we traverse the `comp_graph` and mostly ignore\n", @@ -556,28 +572,35 @@ " If `None`, we default to `[1, 2, 3, 4]`.\n", "\n", " Returns:\n", - " MorphTree of the compartmentalized morphology.\n", + " Graph of the compartmentalized morphology.\n", "\n", " Example usage\n", " ^^^^^^^^^^^^^\n", "\n", " ::\n", "\n", - " from jaxley.io.graph to_swc_morphtree\n", - " morphtree = to_swc_morphtree(\"path_to_swc.swc\")\n", - " comp_morphtree = compartmentalize(morphtree, ncomp=1)\n", + " from jaxley.io.graph swc_to_nx\n", + " swc_graph = swc_to_nx(\"path_to_swc.swc\")\n", + " comp_graph = compartmentalize(swc_graph, ncomp=1)\n", " \"\"\"\n", - " G = _add_missing_swc_attrs(G)\n", + " G = _add_missing_swc_attrs(swc_graph)\n", "\n", - " branches = list_branches(G, ignore_swc_tracing_interruptions=ignore_swc_tracing_interruptions, max_len=max_len, relevant_ids=relevant_type_ids)\n", + " branches = list_branches(\n", + " G,\n", + " ignore_swc_tracing_interruptions=ignore_swc_tracing_interruptions,\n", + " max_len=max_len,\n", + " relevant_ids=relevant_type_ids,\n", + " )\n", " nodes_df = nx_to_pandas(G)[0].astype(float)\n", "\n", " # create new set of indices which arent already used as node indices to label comps\n", " existing_inds = set(nodes_df.index)\n", - " num_new_inds = len(branches)*ncomp\n", + " num_new_inds = len(branches) * ncomp\n", " proposed_inds = set(range(num_new_inds + len(existing_inds)))\n", - " proposed_comp_inds = list(proposed_inds - existing_inds) # avoid overlap w. node indices\n", - " \n", + " proposed_comp_inds = list(\n", + " proposed_inds - existing_inds\n", + " ) # avoid overlap w. node indices\n", + "\n", " # identify tip nodes (degree == 1 -> node appears only once in edges)\n", " nodes_in_edges, node_counts_in_edges = np.unique(G.edges, return_counts=True)\n", " tip_node_inds = nodes_in_edges[node_counts_in_edges == 1]\n", @@ -590,41 +613,50 @@ " xyzr_i = node_attrs[[\"x\", \"y\", \"z\", \"r\"]]\n", " xyzr.append(xyzr_i.values)\n", "\n", - " compute_edge_lens = lambda x: (x.diff(axis=0).fillna(0)**2).sum(axis=1)**.5\n", + " compute_edge_lens = lambda x: (x.diff(axis=0).fillna(0) ** 2).sum(axis=1) ** 0.5\n", " edge_lens = compute_edge_lens(xyzr_i[[\"x\", \"y\", \"z\"]])\n", - " node_attrs[\"l\"] = edge_lens.cumsum() # path length\n", - " \n", + " node_attrs[\"l\"] = edge_lens.cumsum() # path length\n", + "\n", " # For single-point somatata, we set l = 2*r this ensures\n", " # A_cylinder = 2*pi*r*l = 4*pi*r^2 = A_sphere.\n", " if len(branch) == 1:\n", - " node_attrs = node_attrs.loc[branch*2] # duplicate soma node\n", + " node_attrs = node_attrs.loc[branch * 2] # duplicate soma node\n", " radius = node_attrs[\"r\"].iloc[0]\n", - " node_attrs[\"l\"] = np.array([0, 2*radius])\n", + " node_attrs[\"l\"] = np.array([0, 2 * radius])\n", "\n", - " branch_id = node_attrs[\"id\"].iloc[-1] # TODO: better handle mult. ids in branch!\n", + " branch_id = node_attrs[\"id\"].iloc[\n", + " -1\n", + " ] # TODO: how to handle mult. ids in branch!\n", " branch_len = max(node_attrs[\"l\"])\n", " comp_len = branch_len / ncomp\n", - " comp_locs = list(np.linspace(comp_len/2, branch_len - comp_len/2, ncomp))\n", - " \n", + " comp_locs = list(np.linspace(comp_len / 2, branch_len - comp_len / 2, ncomp))\n", + "\n", " # Create node indices and attributes\n", " # branch_inds, branchpoint, comp_id, comp_len\n", " branch_tips = branch[0], branch[-1]\n", - " branch_tip_attrs = [[i, True, node_attrs[\"id\"].iloc[0], 0],\n", - " [i, True, node_attrs[\"id\"].iloc[-1], 0]]\n", - " comp_attrs = [[i, False, branch_id, comp_len]]*ncomp\n", + " branch_tip_attrs = [\n", + " [i, True, node_attrs[\"id\"].iloc[0], 0],\n", + " [i, True, node_attrs[\"id\"].iloc[-1], 0],\n", + " ]\n", + " comp_attrs = [[i, False, branch_id, comp_len]] * ncomp\n", "\n", - " comp_inds = proposed_comp_inds[i*ncomp:(i+1)*ncomp]\n", + " comp_inds = proposed_comp_inds[i * ncomp : (i + 1) * ncomp]\n", " comp_inds = np.array([branch_tips[0], *comp_inds, branch_tips[1]])\n", " comp_attrs = [branch_tip_attrs[0]] + comp_attrs + [branch_tip_attrs[1]]\n", " comp_attrs = np.hstack([comp_inds[:, None], comp_attrs])\n", - " \n", - " # Interpolate xyzr coordinates and combine with attributes\n", - " x = jnp.array([0] + comp_locs + [branch_len]) # 0, branch_len = branchpoints\n", - " xp = jnp.array(node_attrs[\"l\"].values)\n", - " fp = jnp.array(xyzr_i.values)\n", - " #TODO: interpolate r differently!\n", - " comp_attrs = np.hstack([comp_attrs, np.array(v_interp(x, xp, fp))])\n", - " \n", + "\n", + " x = np.array([0] + comp_locs + [branch_len])\n", + " xp = np.array(node_attrs[\"l\"].values)\n", + " fp = np.array(xyzr_i.values)\n", + "\n", + " # TODO: interpolate **r** differently!\n", + " interpolated_coords = np.column_stack(\n", + " [np.interp(x, xp, fp[:, i]) for i in range(fp.shape[1])]\n", + " )\n", + "\n", + " # Combine interpolated coordinates with existing attributes\n", + " comp_attrs = np.hstack([comp_attrs, interpolated_coords])\n", + "\n", " # remove tip nodes\n", " comp_attrs = comp_attrs[1:] if branch_tips[0] in tip_node_inds else comp_attrs\n", " comp_attrs = comp_attrs[:-1] if branch_tips[1] in tip_node_inds else comp_attrs\n", @@ -636,17 +668,17 @@ " branch_nodes = np.concatenate(branch_nodes)\n", " comp_attrs_keys = [\"idx\", \"branch\", \"branchpoint\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", - " \n", + "\n", " int_cols = [\"idx\", \"branch\", \"id\"]\n", " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", - " \n", + "\n", " bool_cols = [\"branchpoint\"]\n", " comp_df[bool_cols] = comp_df[bool_cols].astype(bool)\n", "\n", " # threshold radius\n", " if min_radius is not None:\n", " comp_df[\"r\"] = np.maximum(comp_df[\"r\"], min_radius)\n", - " \n", + "\n", " # drop duplicated branch nodes\n", " comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", " comp_df = comp_df.set_index(\"idx\")\n", @@ -662,7 +694,8 @@ " G = nx.relabel_nodes(G, {n: i for i, n in enumerate(G.nodes)})\n", " return G\n", "\n", - "def _add_jaxley_meta_data(G: MorphTree) -> MorphTree:\n", + "\n", + "def _add_jaxley_meta_data(G: nx.DiGraph) -> nx.DiGraph:\n", " \"\"\"Add attributes to and rename existing attributes of the compartalized morphology.\n", "\n", " Makes the imported and compartmentalized morphology compatible with jaxley.\n", @@ -670,7 +703,7 @@ " nodes_df, edge_df, global_attrs = nx_to_pandas(G)\n", " module_global_attrs = pd.Series({\"channels\": {}, \"synapses\": {}, \"group_names\": []})\n", " global_attrs = pd.concat([global_attrs, module_global_attrs])\n", - " \n", + "\n", " # rename/reformat existing columns\n", " group_ids = {0: \"undefined\", 1: \"soma\", 2: \"axon\", 3: \"basal\", 4: \"apical\"}\n", " for group_id, group_name in group_ids.items():\n", @@ -686,12 +719,13 @@ " nodes_df[\"capacitance\"] = 1.0\n", " nodes_df[\"v\"] = -70.0\n", " nodes_df[\"axial_resistivity\"] = 1000.0\n", - " #TODO: rename to cell_index > cell, comp_index > comp, branch_index > branch\n", + " # TODO: rename to cell_index > cell, comp_index > comp, branch_index > branch\n", " nodes_df[\"comp_index\"] = np.arange(len(nodes_df))\n", " nodes_df[\"cell_index\"] = 0\n", "\n", " return pandas_to_nx(nodes_df, edge_df, global_attrs)\n", "\n", + "\n", "def _replace_branchpoints_with_edges(G: nx.DiGraph) -> nx.DiGraph:\n", " \"\"\"Replace branchpoint nodes with edges connecting parent and children.\"\"\"\n", " G.add_edges_from([(i, j, {\"branch_edge\": False}) for i, j in G.edges])\n", @@ -701,25 +735,28 @@ " for n in branchpoints:\n", " parent = next(G.predecessors(n))\n", " children = list(G.successors(n))\n", - " \n", + "\n", " # remove branchpoint and connect parent to children\n", " G.remove_node(n)\n", " G.add_edges_from([(parent, c) for c in children], **branch_edge_attrs)\n", - " \n", + "\n", " for i, n in enumerate(G.nodes):\n", " G.nodes[n].pop(\"branchpoint\")\n", " # TODO: Can we skip relabeling comps and reindexing the dataframe?\n", " G.nodes[n][\"comp_index\"] = i\n", " G = nx.relabel_nodes(G, {n: i for i, n in enumerate(G.nodes)})\n", - " \n", + "\n", " return G\n", "\n", - "def _compute_branch_parents(node_df: pd.DataFrame, edge_df: pd.DataFrame) -> List[List[int]]:\n", + "\n", + "def _compute_branch_parents(\n", + " node_df: pd.DataFrame, edge_df: pd.DataFrame\n", + ") -> List[List[int]]:\n", " \"\"\"Compute the parent structure of the branch graph (for each cell).\n", "\n", " Args:\n", - " node_df: The node dataframe of the MorphTree.\n", - " edge_df: The edge dataframe of the MorphTree.\n", + " node_df: The node dataframe of the graph.\n", + " edge_df: The edge dataframe of the graph.\n", "\n", " Returns:\n", " The parent structure of the branch graph for each cell.\n", @@ -728,13 +765,17 @@ " parent_inds = branch_edge_inds.get_level_values(0)\n", " child_inds = branch_edge_inds.get_level_values(1)\n", "\n", - " branch_edges = pd.DataFrame({\n", - " \"parent_branch\": node_df[\"branch_index\"].loc[parent_inds].values,\n", - " \"child_branch\": node_df[\"branch_index\"].loc[child_inds].values\n", - " })\n", + " branch_edges = pd.DataFrame(\n", + " {\n", + " \"parent_branch\": node_df[\"branch_index\"].loc[parent_inds].values,\n", + " \"child_branch\": node_df[\"branch_index\"].loc[child_inds].values,\n", + " }\n", + " )\n", "\n", " acc_parents = []\n", - " parent_branch_inds = branch_edges.set_index(\"child_branch\").sort_index()[\"parent_branch\"]\n", + " parent_branch_inds = branch_edges.set_index(\"child_branch\").sort_index()[\n", + " \"parent_branch\"\n", + " ]\n", "\n", " for branch_inds in node_df.groupby(\"cell_index\")[\"branch_index\"].unique():\n", " root_branch_idx = branch_inds[0]\n", @@ -742,27 +783,29 @@ " acc_parents.append([-1] + parents.tolist())\n", " return acc_parents\n", "\n", + "\n", "def _build_module(G: nx.DiGraph) -> jx.Module:\n", " \"\"\"Build a Module from a compartmentalized morphology.\n", "\n", - " This function builds a Module from a MorphTree.\n", + " This function builds a Module from a nx.DiGraph that has been compartmentalized.\n", "\n", " Args:\n", - " G: The MorphTree to build the Module from.\n", + " G: The graph to build the Module from.\n", "\n", " Returns:\n", - " The Module built from the MorphTree.\n", + " The Module built from the graph.\n", " \"\"\"\n", " node_df, edge_df, global_attrs = nx_to_pandas(G)\n", "\n", " nodes_per_branch = node_df[\"branch_index\"].value_counts()\n", - " assert nodes_per_branch.nunique() == 1, (\"`from_graph()` does not support a varying number of compartments in each branch.\")\n", - " \n", - " # TODO: MorphTree backend: read the MorphTree straight into the Module\n", - " acc_parents = _compute_branch_parents(node_df, edge_df)\n", - " module = _build_module_scaffold(node_df, parent_branches=acc_parents, xyzr=global_attrs[\"xyzr\"])\n", + " assert (\n", + " nodes_per_branch.nunique() == 1\n", + " ), \"`from_graph()` does not support a varying number of compartments in each branch.\"\n", "\n", - " # TODO: add groups\n", + " acc_parents = _compute_branch_parents(node_df, edge_df)\n", + " module = _build_module_scaffold(\n", + " node_df, parent_branches=acc_parents, xyzr=global_attrs[\"xyzr\"]\n", + " )\n", "\n", " node_df.columns = [\n", " \"global_\" + col if \"local\" not in col and \"index\" in col else col\n", @@ -778,502 +821,47 @@ " # add all the extra attrs\n", " module.synapses = global_attrs[\"synapses\"]\n", " module.channels = global_attrs[\"channels\"]\n", + " module.group_names = global_attrs[\"group_names\"]\n", " module.membrane_current_names = [c.current_name for c in module.channels]\n", " module.synapse_names = [s._name for s in module.synapses]\n", - " \n", - " return module" - ] - }, - { - "cell_type": "code", - "execution_count": 304, - "metadata": {}, - "outputs": [], - "source": [ - "morph_tree = swc_to_nx(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", - "morph_comps = compartmentalize(morph_tree, ncomp=1)\n", - "morph_comps = _add_jaxley_meta_data(morph_comps)\n", - "morph_comps = _replace_branchpoints_with_edges(morph_comps)\n", - "cell = _build_module(morph_comps)" - ] - }, - { - "cell_type": "code", - "execution_count": 113, - "metadata": {}, - "outputs": [], - "source": [ - "def swc_to_morphtree(fname: str, num_lines: Optional[int] = None) -> MorphTree:\n", - " \"\"\"Read a SWC file and return a MorphTree.\n", - "\n", - " The graph is read such that each entry in the swc file becomes a graph node\n", - " with the column attributes (id, x, y, z, r). Then each node is connected to its\n", - " designated parent via an edge.\n", - "\n", - " Args:\n", - " fname: Path to the swc file.\n", - " num_lines: Number of lines to read from the file. If None, all lines are read.\n", - "\n", - " Returns:\n", - " A MorphTree of the traced morphology. It has attributes:\n", - " nodes: {'id': 1, 'x': 0.0, 'y': 0.0, 'z': 0.0, 'r': 1.0, 'p': -1}\n", - " edges: {}\n", - "\n", - " Example usage\n", - " ^^^^^^^^^^^^^\n", - "\n", - " ::\n", - "\n", - " from jaxley.io.graph swc_to_morph_tree\n", - " morphtree = swc_to_morph_tree(\"path_to_swc.swc\")\n", - " \"\"\"\n", - " i_id_xyzr_p = np.loadtxt(fname)[:num_lines]\n", - " \n", - " node_attrs, edge_attrs = {}, {}\n", - " for i, id, x, y, z, r, p in i_id_xyzr_p.tolist(): # tolist: np.float64 -> float\n", - " node_attrs[int(i)] = {\"id\": int(id), \"x\": x, \"y\": y, \"z\": z, \"r\": r}\n", - " if p != -1:\n", - " edge_attrs[int(p), int(i)] = {}\n", - " \n", - " return MorphTree(node_attrs, edge_attrs)\n", - "\n", - "def _find_swc_tracing_interruptions(tree: MorphTree) -> list[tuple[int, int]]:\n", - " \"\"\"Identify discontinuities in the swc tracing order.\n", - "\n", - " Some swc files contain artefacts, where tracing of the same neurite was done\n", - " in disconnected pieces. NEURON swc reader introduce a break in the trace at these \n", - " points, since they parse the file in order. This leads to split branches, which \n", - " should be one. This function identifies these points in the graph.\n", - "\n", - " Example swc file:\n", - " # branch 1\n", - " 1 1 0.0 0.0 0.0 1.0 -1\n", - " 2 1 1.0 0.0 0.0 1.0 1\n", - " 3 1 2.0 0.0 0.0 1.0 2\n", - " # branch 2\n", - " 4 2 3.0 1.0 0.0 1.0 3\n", - " 5 2 4.0 2.0 0.0 1.0 4\n", - " # branch 3\n", - " 6 3 3.0 -1.0 0.0 1.0 3\n", - " 7 3 4.0 -2.0 0.0 1.0 6\n", - " 8 3 5.0 -3.0 0.0 1.0 7\n", - " # ammend branch 2\n", - " 9 4 5.0 3.0 0.0 1.0 5\n", - "\n", - " Args:\n", - " tree: MorphTree tracing of swc file.\n", - "\n", - " Returns:\n", - " An array of edges where tracing is discontinous.\n", - " \"\"\"\n", - " G = tree.to_nx()\n", - " degree_is_2 = lambda n: G.out_degree(n) + G.in_degree(n) == 2\n", - "\n", - " interrupt_edges = []\n", - " for n in G.nodes:\n", - " if len(parents := list(G.predecessors(n))) > 0:\n", - " p = parents[0] \n", - " if p != n-1 and degree_is_2(n) and degree_is_2(p):\n", - " interrupt_edges.append((p,n))\n", - " return interrupt_edges\n", - "\n", - "def _split_branches(branches: list[list[int]], split_edges: list[tuple[int, int]]) -> list[list[int]]:\n", - " \"\"\"Split branches at the given edges.\n", - "\n", - " Args:\n", - " branches: List of branches, each represented as list of nodes.\n", - " split_edges: List of edges between nodes where tracing is discontinous.\n", - "\n", - " Returns:\n", - " An updated list of branches.\n", - " \"\"\"\n", - " for (p, n) in split_edges:\n", - " for i, branch in enumerate(branches):\n", - " if n in branch:\n", - " split_idx = branch.index(n)\n", - " branches[i:i+1] = [branch[:split_idx], branch[split_idx:]]\n", - " break\n", - " return branches\n", - "\n", - "def list_branches(tree: MorphTree, return_branchpoints: bool = False, ignore_swc_tracing_interruptions=True, relevant_ids: Optional[List[int]] = [1,2,3,4], max_len: Optional[float] = None) -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", - " \"\"\"Get all uninterrupted paths in the traced morphology (i.e. branches).\n", - "\n", - " The graph is traversed depth-first starting from the first found leaf node.\n", - " Nodes are considered to be part of a branch if they have only one parent and one\n", - " child, which are both of the same type (i.e. have the same `id`). Nodes which are\n", - " branchpoints or leafs are considered start / end points of a branch. A branchpoint\n", - " can start multiple branches.\n", - "\n", - " Args:\n", - " tree: MorphTree tracing of swc file.\n", - " return_branchpoints: Whether to return the branchpoints and edges between them\n", - " seperately.\n", - " ignore_swc_tracing_interruptions: Whether to ignore discontinuities in the swc\n", - " tracing order. If False, this will result in split branches at these points.\n", - " relevant_ids: All type ids that are not in this list will be ignored for\n", - " tracing the morphology. This means that branches which have multiple type\n", - " ids (which are not in `relevant_ids`) will be considered as one branch.\n", - " Defaults to `[1, 2, 3, 4]`.\n", - "\n", - " Returns:\n", - " A list of linear paths in the graph. Each path is represented as list of nodes.\n", - " \"\"\"\n", - " G = tree.to_nx().to_undirected()\n", - " branches = []\n", - " branchpoints = set()\n", - " visited = set()\n", - "\n", - " was_visited = lambda n1, n2: (n1, n2) in visited or (n2, n1) in visited\n", - " id_of = lambda n: G.nodes[n][\"id\"]\n", - " is_soma = lambda n: id_of(n) == 1\n", - " soma_nodes = lambda: [i for i, n in G.nodes.items() if n[\"id\"] == 1]\n", - "\n", - " def is_branchpoint_or_tip(n: int) -> bool:\n", - " if G.degree(n) == 2:\n", - " i,j = G.neighbors(n)\n", - " # trace dir matters here! For segment with node IDs: [1, 1, 2, 2]\n", - " # -> [[1,1], [1,2,2]] \n", - " # <- [[2,2], [2,1,1]] \n", - " return not same_id(n, j)\n", - " \n", - " is_leaf = G.degree(n) <= 1\n", - " is_branching = G.degree(n) > 2\n", - " return is_leaf or is_branching\n", - " \n", - " def same_id(n1: int, n2: int) -> bool:\n", - " has_id = lambda n: id_of(n) in relevant_ids if \"id\" in G.nodes[n] else False\n", - " if has_id(n1) and has_id(n2):\n", - " return id_of(n1) == id_of(n2)\n", - " return True\n", - "\n", - " def walk_path(start: int, succ: int) -> List[int]:\n", - " \"\"\"Walk from start to succ, recording new nodes until a branching node is hit.\"\"\"\n", - " path = [start, succ]\n", - " visited.add((start, succ))\n", - " \n", - " while G.degree(succ) == 2:\n", - " next_node = next(n for n in G.neighbors(succ) if n != path[-2])\n", - "\n", - " if was_visited(succ, next_node) or is_branchpoint_or_tip(succ):\n", - " break\n", - " \n", - " path.append(next_node)\n", - " visited.add((succ, next_node))\n", - " succ = next_node\n", - "\n", - " return path\n", - "\n", - " leaf = next(n for n in G.nodes if G.degree(n) == 1)\n", - " single_soma = len(soma_nodes()) == 1\n", - " for node in nx.dfs_tree(G, leaf):\n", - " if single_soma and is_soma(node):\n", - " branches.append([node])\n", - "\n", - " elif is_branchpoint_or_tip(node):\n", - " branchpoints.add(node)\n", - " for succ in G.neighbors(node):\n", - " if not was_visited(node, succ):\n", - " branches.append(walk_path(node, succ))\n", - " \n", - " # split branches\n", - " if not ignore_swc_tracing_interruptions: # TODO: fix!\n", - " split_edges = _find_swc_tracing_interruptions(tree)\n", - " branches = _split_branches(branches, split_edges)\n", - " branchpoints.update(set(p for (p,n) in split_edges))\n", - " \n", - " # TODO: add max_len\n", - " if max_len is not None:\n", - " raise NotImplementedError(\"max_len not implemented\")\n", - "\n", - "\n", - " if return_branchpoints:\n", - " branchpoint_edges = sum([list(G.edges(n)) for n in branchpoints], [])\n", - " return branches, branchpoints, branchpoint_edges\n", - " return branches\n", - "\n", - "def _add_missing_swc_attrs(tree: MorphTree) -> MorphTree:\n", - " \"\"\"Add missing swc attributes to a MorphTree.\n", - "\n", - " Allows to specify morphology from just edges.\n", - "\n", - " Args:\n", - " tree: The MorphTree to add missing attributes to.\n", - "\n", - " Returns:\n", - " The MorphTree with missing attributes set to their defaults.\n", - " \"\"\"\n", - " defaults = {\"id\": 0, \"r\": 1}\n", - " node_attr_keys = next(iter(tree.node_attrs.values())).keys()\n", - " xyz = compute_xyz(tree) if \"x\" not in node_attr_keys else {}\n", - " for n, (x, y, z) in xyz.items():\n", - " tree.node_attrs[n][\"x\"] = x\n", - " tree.node_attrs[n][\"y\"] = y\n", - " tree.node_attrs[n][\"z\"] = z\n", - "\n", - " missing_attrs = {k: v for k, v in defaults.items() if k not in node_attr_keys}\n", - " for n in tree.node_attrs:\n", - " tree.node_attrs[n].update(missing_attrs)\n", - " return tree\n", - "\n", - "def compartmentalize(tree: MorphTree, ncomp: int = 1, min_radius: Optional[float] = None, max_len: Optional[float] = None, ignore_swc_tracing_interruptions: bool = True, relevant_type_ids: Optional[List[int]] = [1,2,3,4]) -> MorphTree:\n", - " \"\"\"Return a networkX graph that indicates the compartment structure.\n", - "\n", - " Build a new graph made up of compartments in every branch. These compartments are\n", - " spaced at equidistant points along the branch. Node attributes, like radius are\n", - " linearly interpolated along its length.\n", - "\n", - " Example: 4 compartments | edges = - | nodes = o | comp_nodes = x\n", - " o-----------o----------o---o---o---o--------o\n", - " o-------x---o----x-----o--xo---o---ox-------o\n", - "\n", - " This function returns a MorphTree. The graph is directed only because every\n", - " compartment tracks the xyzr coordinates of the associated SWC file. These xyzr\n", - " coordinates are ordered by the order of the traversal of the swc_graph. In later\n", - " methods (e.g. build_solve_graph), we traverse the `comp_graph` and mostly ignore\n", - " the directionality of the edges, but we only use the directionality to reverse the\n", - " xyzr coordinates if necessary.\n", - "\n", - " Args:\n", - " swc_graph: Graph generated by `to_swc_graph()`.\n", - " ncomp: How many compartments per branch to insert.\n", - " root: The root branch from which to start tracing the nodes. This defines the\n", - " branch indices.\n", - " min_radius: Minimal radius for each compartment.\n", - " max_len: Maximal length for each branch. Longer branches are split into\n", - " separate branches.\n", - " ignore_swc_tracing_interruptions: If `False`, it this function automatically\n", - " starts a new branch when a section is traced with interruptions.\n", - " relevant_type_ids: All type ids that are not in this list will be ignored for\n", - " tracing the morphology. This means that branches which have multiple type\n", - " ids (which are not in `relevant_type_ids`) will be considered as one branch.\n", - " If `None`, we default to `[1, 2, 3, 4]`.\n", - "\n", - " Returns:\n", - " MorphTree of the compartmentalized morphology.\n", - "\n", - " Example usage\n", - " ^^^^^^^^^^^^^\n", "\n", - " ::\n", + " return module\n", "\n", - " from jaxley.io.graph to_swc_morphtree\n", - " morphtree = to_swc_morphtree(\"path_to_swc.swc\")\n", - " comp_morphtree = compartmentalize(morphtree, ncomp=1)\n", - " \"\"\"\n", - " tree = _add_missing_swc_attrs(tree)\n", "\n", - " branches = list_branches(tree, ignore_swc_tracing_interruptions=ignore_swc_tracing_interruptions, max_len=max_len, relevant_ids=relevant_type_ids)\n", - " nodes_df = tree.to_pandas()[0].astype(float)\n", + "def nx_to_module(swc_graph: nx.DiGraph, ncomp: int = 1) -> jx.Module:\n", + " comp_graph = compartmentalize(swc_graph, ncomp=ncomp)\n", + " comp_graph = _add_jaxley_meta_data(comp_graph)\n", + " solve_graph = _replace_branchpoints_with_edges(comp_graph)\n", + " module = _build_module(solve_graph)\n", + " return module\n", "\n", - " # create new set of indices which arent already used as node indices to label comps\n", - " existing_inds = set(nodes_df.index)\n", - " num_new_inds = len(branches)*ncomp\n", - " proposed_inds = set(range(num_new_inds + len(existing_inds)))\n", - " proposed_comp_inds = list(proposed_inds - existing_inds) # avoid overlap w. node indices\n", - " \n", - " # identify tip nodes (degree == 1 -> node appears only once in edges)\n", - " nodes_in_edges, node_counts_in_edges = np.unique(tree.edges, return_counts=True)\n", - " tip_node_inds = nodes_in_edges[node_counts_in_edges == 1]\n", "\n", - " # collect comps and comp_edges\n", - " branch_nodes, branch_edges = [], []\n", - " xyzr = []\n", - " for i, branch in enumerate(branches):\n", - " node_attrs = nodes_df.loc[branch]\n", - " xyzr_i = node_attrs[[\"x\", \"y\", \"z\", \"r\"]]\n", - " xyzr.append(xyzr_i.values)\n", - "\n", - " compute_edge_lens = lambda x: (x.diff(axis=0).fillna(0)**2).sum(axis=1)**.5\n", - " edge_lens = compute_edge_lens(xyzr_i[[\"x\", \"y\", \"z\"]])\n", - " node_attrs[\"l\"] = edge_lens.cumsum() # path length\n", - " \n", - " # For single-point somatata, we set l = 2*r this ensures\n", - " # A_cylinder = 2*pi*r*l = 4*pi*r^2 = A_sphere.\n", - " if len(branch) == 1:\n", - " node_attrs = node_attrs.loc[branch*2] # duplicate soma node\n", - " radius = node_attrs[\"r\"].iloc[0]\n", - " node_attrs[\"l\"] = np.array([0, 2*radius])\n", - "\n", - " branch_id = node_attrs[\"id\"].iloc[-1] # TODO: better handle mult. ids in branch!\n", - " branch_len = max(node_attrs[\"l\"])\n", - " comp_len = branch_len / ncomp\n", - " comp_locs = list(np.linspace(comp_len/2, branch_len - comp_len/2, ncomp))\n", - " \n", - " # Create node indices and attributes\n", - " # branch_inds, branchpoint, comp_id, comp_len\n", - " branch_tips = branch[0], branch[-1]\n", - " branch_tip_attrs = [[i, True, node_attrs[\"id\"].iloc[0], 0],\n", - " [i, True, node_attrs[\"id\"].iloc[-1], 0]]\n", - " comp_attrs = [[i, False, branch_id, comp_len]]*ncomp\n", + "def read_swc(fname: str) -> jx.Module:\n", + " swc_graph = swc_to_nx(fname)\n", + " return nx_to_module(swc_graph)\n", "\n", - " comp_inds = proposed_comp_inds[i*ncomp:(i+1)*ncomp]\n", - " comp_inds = np.array([branch_tips[0], *comp_inds, branch_tips[1]])\n", - " comp_attrs = [branch_tip_attrs[0]] + comp_attrs + [branch_tip_attrs[1]]\n", - " comp_attrs = np.hstack([comp_inds[:, None], comp_attrs])\n", - " \n", - " # Interpolate xyzr coordinates and combine with attributes\n", - " x = jnp.array([0] + comp_locs + [branch_len]) # 0, branch_len = branchpoints\n", - " xp = jnp.array(node_attrs[\"l\"].values)\n", - " fp = jnp.array(xyzr_i.values)\n", - " #TODO: interpolate r differently!\n", - " comp_attrs = np.hstack([comp_attrs, np.array(v_interp(x, xp, fp))])\n", - " \n", - " # remove tip nodes\n", - " comp_attrs = comp_attrs[1:] if branch_tips[0] in tip_node_inds else comp_attrs\n", - " comp_attrs = comp_attrs[:-1] if branch_tips[1] in tip_node_inds else comp_attrs\n", "\n", - " # Store edges and nodes\n", - " branch_edges.append(list(zip(comp_attrs[:-1, 0], comp_attrs[1:, 0])))\n", - " branch_nodes.append(comp_attrs)\n", + "# def module_to_nx(module: jx.Module) -> nx.DiGraph:\n", + "# global_attrs = {}\n", + "# global_attrs[\"group_names\"] = module.group_names\n", + "# global_attrs[\"synapses\"] = module.synapses\n", + "# global_attrs[\"channels\"] = module.channels\n", "\n", - " branch_nodes = np.concatenate(branch_nodes)\n", - " comp_attrs_keys = [\"idx\", \"branch\", \"branchpoint\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", - " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", - " \n", - " int_cols = [\"idx\", \"branch\", \"id\"]\n", - " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", - " \n", - " bool_cols = [\"branchpoint\"]\n", - " comp_df[bool_cols] = comp_df[bool_cols].astype(bool)\n", + "# node_attrs = module.nodes\n", + "# edge_attrs = module.edges\n", "\n", - " # threshold radius\n", - " if min_radius is not None:\n", - " comp_df[\"r\"] = np.maximum(comp_df[\"r\"], min_radius)\n", - " \n", - " # drop duplicated branch nodes\n", - " comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", - " comp_df = comp_df.set_index(\"idx\")\n", - " comp_attrs = comp_df.to_dict(orient=\"index\")\n", + "# node_attrs = node_attrs.drop(columns=[col for col in node_attrs.columns if col.startswith(\"local_\")])\n", "\n", - " # create comp edges\n", - " comp_edges = sum(branch_edges, [])\n", - " comp_edge_attrs = {(i,j): {\"comp_edge\": True, \"synapse\": False} for i,j in comp_edges}\n", - "\n", - " comp_tree = MorphTree(comp_attrs, comp_edge_attrs, {\"xyzr\": xyzr})\n", - " comp_tree = comp_tree.reindex_nodes(dict(zip(comp_df.index, range(len(comp_df)))))\n", - " return comp_tree\n", - "\n", - "def _add_jaxley_meta_data(tree: MorphTree) -> MorphTree:\n", - " \"\"\"Add attributes to and rename existing attributes of the compartalized morphology.\n", - "\n", - " Makes the imported and compartmentalized morphology compatible with jaxley.\n", - " \"\"\"\n", - " nodes_df, edge_df, global_attrs = tree.to_pandas()\n", - " module_global_attrs = pd.Series({\"channels\": {}, \"synapses\": {}, \"group_names\": []})\n", - " global_attrs = pd.concat([global_attrs, module_global_attrs])\n", - " \n", - " # rename/reformat existing columns\n", - " group_ids = {0: \"undefined\", 1: \"soma\", 2: \"axon\", 3: \"basal\", 4: \"apical\"}\n", - " for group_id, group_name in group_ids.items():\n", - " where_group = nodes_df[\"id\"] == group_id\n", - " if where_group.any():\n", - " global_attrs[\"group_names\"].append(group_name)\n", - " nodes_df[group_name] = where_group\n", - " nodes_df = nodes_df.drop(columns=[\"id\"])\n", - " module_col_names = {\"r\": \"radius\", \"l\": \"length\", \"branch\": \"branch_index\"}\n", - " nodes_df = nodes_df.rename(module_col_names, axis=1)\n", - "\n", - " # new columns\n", - " nodes_df[\"capacitance\"] = 1.0\n", - " nodes_df[\"v\"] = -70.0\n", - " nodes_df[\"axial_resistivity\"] = 1000.0\n", - " #TODO: rename to cell_index > cell, comp_index > comp, branch_index > branch\n", - " nodes_df[\"comp_index\"] = np.arange(len(nodes_df))\n", - " nodes_df[\"cell_index\"] = 0\n", - "\n", - " return MorphTree.from_pandas(nodes_df, edge_df, global_attrs)\n", - "\n", - "def _replace_branchpoints_with_edges(tree: MorphTree) -> MorphTree:\n", - " \"\"\"Replace branchpoint nodes with edges connecting parent and children.\"\"\"\n", - " G = tree.to_nx()\n", - " G.add_edges_from([(i, j, {\"branch_edge\": False}) for i, j in G.edges])\n", - " branch_edge_attrs = {\"comp_edge\": True, \"synapse\": False, \"branch_edge\": True}\n", - "\n", - " branchpoints = [n for n in G.nodes if G.nodes[n][\"branchpoint\"]]\n", - " for n in branchpoints:\n", - " parent = next(G.predecessors(n))\n", - " children = list(G.successors(n))\n", - " \n", - " # remove branchpoint and connect parent to children\n", - " G.remove_node(n)\n", - " G.add_edges_from([(parent, c) for c in children], **branch_edge_attrs)\n", - " \n", - " for i, n in enumerate(G.nodes):\n", - " G.nodes[n].pop(\"branchpoint\")\n", - " # TODO: Can we skip relabeling comps and reindexing the dataframe?\n", - " G.nodes[n][\"comp_index\"] = i\n", - " G = nx.relabel_nodes(G, {n: i for i, n in enumerate(G.nodes)})\n", - " \n", - " return MorphTree.from_nx(G)\n", - "\n", - "def _compute_branch_parents(node_df: pd.DataFrame, edge_df: pd.DataFrame) -> List[List[int]]:\n", - " \"\"\"Compute the parent structure of the branch graph (for each cell).\n", - "\n", - " Args:\n", - " node_df: The node dataframe of the MorphTree.\n", - " edge_df: The edge dataframe of the MorphTree.\n", - "\n", - " Returns:\n", - " The parent structure of the branch graph for each cell.\n", - " \"\"\"\n", - " branch_edge_inds = edge_df.index[edge_df[\"branch_edge\"]]\n", - " parent_inds = branch_edge_inds.get_level_values(0)\n", - " child_inds = branch_edge_inds.get_level_values(1)\n", - "\n", - " branch_edges = pd.DataFrame({\n", - " \"parent_branch\": node_df[\"branch_index\"].loc[parent_inds].values,\n", - " \"child_branch\": node_df[\"branch_index\"].loc[child_inds].values\n", - " })\n", - "\n", - " acc_parents = []\n", - " parent_branch_inds = branch_edges.set_index(\"child_branch\").sort_index()[\"parent_branch\"]\n", - "\n", - " for branch_inds in node_df.groupby(\"cell_index\")[\"branch_index\"].unique():\n", - " root_branch_idx = branch_inds[0]\n", - " parents = parent_branch_inds.loc[branch_inds[1:]] - root_branch_idx\n", - " acc_parents.append([-1] + parents.tolist())\n", - " return acc_parents\n", - "\n", - "def _build_module(morph_comps: MorphTree) -> jx.Module:\n", - " \"\"\"Build a Module from a compartmentalized morphology.\n", - "\n", - " This function builds a Module from a MorphTree.\n", - "\n", - " Args:\n", - " morph_comps: The MorphTree to build the Module from.\n", - "\n", - " Returns:\n", - " The Module built from the MorphTree.\n", - " \"\"\"\n", - " node_df, edge_df, global_attrs = morph_comps.to_pandas()\n", - "\n", - " nodes_per_branch = node_df[\"branch_index\"].value_counts()\n", - " assert nodes_per_branch.nunique() == 1, (\"`from_graph()` does not support a varying number of compartments in each branch.\")\n", - " \n", - " # TODO: MorphTree backend: read the MorphTree straight into the Module\n", - " acc_parents = _compute_branch_parents(node_df, edge_df)\n", - " module = _build_module_scaffold(node_df, parent_branches=acc_parents, xyzr=global_attrs[\"xyzr\"])\n", - "\n", - " # TODO: add groups\n", - "\n", - " node_df.columns = [\n", - " \"global_\" + col if \"local\" not in col and \"index\" in col else col\n", - " for col in node_df.columns\n", - " ]\n", - "\n", - " synapse_edges = edge_df[edge_df.synapse]\n", - "\n", - " # set column-wise. preserves cols not in df.\n", - " module.nodes[node_df.columns] = node_df\n", - " module.edges = synapse_edges if not synapse_edges.empty else module.edges\n", - "\n", - " # add all the extra attrs\n", - " module.synapses = global_attrs[\"synapses\"]\n", - " module.channels = global_attrs[\"channels\"]\n", - " module.membrane_current_names = [c.current_name for c in module.channels]\n", - " module.synapse_names = [s._name for s in module.synapses]\n", - " \n", - " return module" + "# return pandas_to_nx(node_attrs, edge_attrs, global_attrs)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "cell = read_swc(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")" ] }, { @@ -2312,39 +1900,6 @@ "# plt.tight_layout()\n", "# plt.show()" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Simple and elegant solution using tree_map\n", - "inner_trees = list(morph_comps.node_attrs.values())\n", - "jax_node_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *inner_trees)\n", - "\n", - "print(\"Original structure (first few nodes):\")\n", - "for i, (k, v) in enumerate(morph_comps.node_attrs.items()):\n", - " print(f\"Node {k}: {v}\")\n", - " if i >= 2:\n", - " break\n", - "\n", - "print(f\"\\nTransformed to arrays:\")\n", - "for attr, values in jax_node_attrs.items():\n", - " if hasattr(values, 'shape'):\n", - " print(f\"{attr}: {type(values).__name__} with shape {values.shape}\")\n", - " else:\n", - " print(f\"{attr}: {type(values).__name__} with length {len(values)}\")\n", - "\n", - "print(f\"\\nSample values:\")\n", - "for attr, values in jax_node_attrs.items():\n", - " if hasattr(values, 'shape'):\n", - " print(f\"{attr}: {values[:3]}\") # Show first 3 values\n", - " else:\n", - " print(f\"{attr}: {values[:3]}\") # Show first 3 values\n", - " if len(jax_node_attrs) > 10: # Don't print too many\n", - " break\n" - ] } ], "metadata": { From b664d090e626765e1494b5c640323d259912cef3 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Wed, 11 Jun 2025 14:55:01 +0200 Subject: [PATCH 20/24] wip: stash --- dev.ipynb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/dev.ipynb b/dev.ipynb index ff7a65e33..ffd111a03 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -270,6 +270,23 @@ " return pos" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nodes = {\"idx\": jnp.array([0,1,2,3])}\n", + "# insert channel into comp 0\n", + "nodes = {\"idx\": jnp.array([0,1,2,3]),\n", + " \"gNa\": jnp.array([0.1, None, None, None])\n", + " }\n", + "# insert channel into comp 2\n", + "nodes = {\"idx\": jnp.array([0,1,2,3]),\n", + " \"gNa\": jnp.array([0.1,None, 0.1, None])\n", + " }" + ] + }, { "cell_type": "code", "execution_count": 29, From 70f68b31929ae32eba83b2b0e3c473d9b44df6bd Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Mon, 16 Jun 2025 14:03:33 +0200 Subject: [PATCH 21/24] wip: save wip. [skip ci]. --- dev.ipynb | 1699 +++++++++++++++++------------------------------------ 1 file changed, 548 insertions(+), 1151 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index ffd111a03..d9893f929 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -49,175 +49,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ - "@jax.tree_util.register_dataclass\n", - "@dataclass\n", - "class MorphTree:\n", - " \"\"\"MorphTree is a custom cataclass that holds the node and edge attributes of a morphology.\n", - " \n", - " MorphTree is used to store the node and edge attributes of a morphology / jaxley Module\n", - " as a pytree, to allow for easy manipulation of the Module / morphology parameters \n", - " using jax transformations.\n", - "\n", - " MorphTree also allows for easy conversion to and from pandas DataFrames, and networkx \n", - " DiGraphs, as well as basic convenience functions for plotting and renaming or reordering\n", - " of nodes and edges.\n", - " \"\"\"\n", - " node_attrs: Dict[int, Dict[str, Any]]\n", - " edge_attrs: Dict[Tuple[int, int], Dict[str, Any]]\n", - " global_attrs: Dict[str, Any] = field(default_factory=dict)\n", - "\n", - " @property\n", - " def nodes(self) -> jnp.ndarray:\n", - " \"\"\"Returns the node indices as a jax array.\"\"\"\n", - " return jnp.array(list(self.node_attrs.keys())).astype(int)\n", - "\n", - " @property\n", - " def edges(self) -> jnp.ndarray:\n", - " \"\"\"Returns the edge indices as a jax array.\"\"\"\n", - " return jnp.array(list(self.edge_attrs.keys())).astype(int)\n", - "\n", - " def __repr__(self) -> str:\n", - " n_nodes = len(self.node_attrs)\n", - " n_edges = len(self.edge_attrs)\n", - "\n", - " node_keys = list(next(iter(self.node_attrs.values())).keys())\n", - " if len(self.edge_attrs) > 0:\n", - " edge_keys = list(next(iter(self.edge_attrs.values())).keys())\n", - " else:\n", - " edge_keys = []\n", - "\n", - " node_attrs = node_keys if len(self.node_attrs) > 0 else []\n", - " edge_attrs = edge_keys if len(self.edge_attrs) > 0 else []\n", - " return f\"MorphTree(nodes={n_nodes}*{node_attrs}, edges={n_edges}*{edge_attrs}, global={list(self.global_attrs.keys())})\"\n", - " \n", - " def __iter__(self):\n", - " \"\"\"Allows unpacking of MorphTree as: node_attrs, edge_attrs, global_attrs = *tree\"\"\"\n", - " yield self.node_attrs\n", - " yield self.edge_attrs\n", - " yield self.global_attrs\n", - " \n", - " def node(self, i: int) -> Dict[str, Any]:\n", - " \"\"\"Returns the node attributes for the node with index i.\"\"\"\n", - " return self.node_attrs[i]\n", - " \n", - " def edge(self, i: int, j: int) -> Dict[str, Any]:\n", - " \"\"\"Returns the edge attributes for the edge between nodes i and j.\"\"\"\n", - " return self.edge_attrs[i, j]\n", - " \n", - " def to_nx(self) -> nx.DiGraph:\n", - " \"\"\"Returns the MorphTree as a networkx DiGraph.\"\"\"\n", - " G = nx.DiGraph()\n", - " G.add_nodes_from(self.node_attrs.items())\n", - " G.add_edges_from((i, j, d) for (i, j), d in self.edge_attrs.items())\n", - " G.graph.update(self.global_attrs)\n", - " return G\n", - " \n", - " @staticmethod\n", - " def from_nx(G: nx.DiGraph) -> MorphTree:\n", - " \"\"\"Returns a MorphTree from a networkx DiGraph.\"\"\"\n", - " node_attrs = {n: G.nodes[n] for n in G.nodes}\n", - " edge_attrs = {(i, j): G.edges[i, j] for i, j in G.edges}\n", - " return MorphTree(node_attrs, edge_attrs, G.graph)\n", - " \n", - " def to_pandas(self, return_global_attrs: bool = True) -> Tuple[pd.DataFrame, pd.DataFrame]:\n", - " \"\"\"Returns the MorphTree as a pandas DataFrame.\"\"\"\n", - " node_df = pd.DataFrame(self.node_attrs.values(), index=self.node_attrs.keys())\n", - " edge_df = pd.DataFrame(self.edge_attrs.values(), index=self.edge_attrs.keys())\n", - " edge_index = pd.MultiIndex.from_arrays(np.array(self.edges).T)\n", - " edge_df = edge_df.set_index(edge_index)\n", - "\n", - " if return_global_attrs:\n", - " return node_df, edge_df, pd.Series(self.global_attrs)\n", - " return node_df, edge_df\n", - " \n", - " @staticmethod\n", - " def from_pandas(node_df: pd.DataFrame, edge_df: pd.DataFrame, global_attrs: pd.Series = pd.Series()) -> MorphTree:\n", - " \"\"\"Returns a MorphTree from a pandas DataFrame.\"\"\"\n", - " node_attrs = node_df.to_dict(orient=\"index\")\n", - " edge_attrs = edge_df.to_dict(orient=\"index\")\n", - " return MorphTree(node_attrs, edge_attrs, global_attrs.to_dict())\n", - " \n", - " def plot(self, dims=(0,1), ax: Optional[Axes] = None, **kwargs: Any) -> Axes:\n", - " \"\"\"Uses networkx to plot the MorphTree.\n", - " \n", - " Args:\n", - " dims: Dimensions to plot (0:x, 1:y, 2:z).\n", - " ax: plt.Axes.\n", - " **kwargs: kwargs for networkx.draw.\n", - "\n", - " Returns:\n", - " The Axes object on which the MorphTree was plotted.\n", - " \"\"\"\n", - " G = self.to_nx()\n", - " pos = {}\n", - " dims2axes = {0: \"x\", 1: \"y\", 2: \"z\"}\n", - " for n, attr in G.nodes(data=True):\n", - " if \"x\" in attr: # assume y is also present\n", - " pos[n] = (attr[dims2axes[dims[0]]], attr[dims2axes[dims[1]]])\n", - " \n", - " ax = ax if ax is not None else plt.gca()\n", - " nx.draw(G, pos, with_labels=True, ax=ax, **kwargs)\n", - " return ax\n", - "\n", - " def reindex_nodes(self, mapping: dict) -> MorphTree:\n", - " \"\"\"Reindexes the nodes of the MorphTree according to the mapping dictionary.\n", - " \n", - " Args:\n", - " mapping: A dict mapping the old to new node indices.\n", - "\n", - " Returns:\n", - " A new MorphTree with the nodes reindexed according to the mapping.\n", - " \"\"\"\n", - " new_node_attrs = {mapping[i]: attrs for i, attrs in self.node_attrs.items()}\n", - " \n", - " new_edge_attrs = {}\n", - " for (i, j), attrs in self.edge_attrs.items():\n", - " new_edge_attrs[(mapping[i], mapping[j])] = attrs\n", - " \n", - " return MorphTree(new_node_attrs, new_edge_attrs, self.global_attrs)\n", - " \n", - " def reorder_tree(self, new_order: jnp.ndarray) -> MorphTree:\n", - " \"\"\"Reorders the nodes of the MorphTree according to the new order.\n", - " \n", - " Edges are flipped to ensure they are always in ascending order.\n", - " \n", - " Args:\n", - " new_order: New node order. new_order[i] is the new index of node i.\n", - "\n", - " Returns:\n", - " A new MorphTree with the nodes reordered according to the new order.\n", - " \"\"\"\n", - " # TODO: check this does what I think it does, i.e. change the edge orientation\n", - " # in order of appearance of the nodes in self.nodes.\n", - " edges = np.array(self.edges)\n", - " np_order = np.array(new_order)\n", - " idx_i = np.where(edges[:,0] == np_order[:, None])[0]\n", - " idx_j = np.where(edges[:,1] == np_order[:, None])[0]\n", - " is_descending = ~(idx_i < idx_j)\n", - " for (i,j) in edges[is_descending]:\n", - " print(i,j)\n", - " self.edge_attrs[j, i] = self.edge_attrs.pop((i, j))\n", - " return self\n", - " \n", - " def subgraph(self, nodes: List[int]) -> MorphTree:\n", - " \"\"\"Returns a subset of nodes in the MorphTree.\n", - "\n", - " Edges are only included if both nodes are in the subgraph.\n", - " \n", - " Args:\n", - " nodes: List of node indices to include in the subgraph.\n", - "\n", - " Returns:\n", - " A new MorphTree containing only the specified nodes and their edges.\n", - " \"\"\"\n", - " node_attrs_subset = {i: self.node_attrs[i] for i in nodes}\n", - " edge_attrs_subset = {(i,j): attrs for (i,j), attrs in self.edge_attrs.items() if i in nodes and j in nodes}\n", - " return MorphTree(node_attrs_subset, edge_attrs_subset, self.global_attrs)\n", - " \n", "# -----------------\n", "# utility functions\n", "# -----------------\n", @@ -272,24 +107,7 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nodes = {\"idx\": jnp.array([0,1,2,3])}\n", - "# insert channel into comp 0\n", - "nodes = {\"idx\": jnp.array([0,1,2,3]),\n", - " \"gNa\": jnp.array([0.1, None, None, None])\n", - " }\n", - "# insert channel into comp 2\n", - "nodes = {\"idx\": jnp.array([0,1,2,3]),\n", - " \"gNa\": jnp.array([0.1,None, 0.1, None])\n", - " }" - ] - }, - { - "cell_type": "code", - "execution_count": 29, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -874,7 +692,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -883,960 +701,446 @@ }, { "cell_type": "code", - "execution_count": 114, + "execution_count": 811, "metadata": {}, "outputs": [], "source": [ - "# G = morph_tree.to_nx()\n", - "# branches = list_branches(morph_tree)\n", - "\n", - "# min_len = 1e-5\n", - "# max_len = 100\n", - "# xyz = lambda i: np.array([G.nodes[i][k] for k in [\"x\", \"y\", \"z\"]])\n", - "# dl = lambda i,j: np.sqrt(((xyz(i) - xyz(j)) ** 2).sum())\n", - "\n", - "# for branch in branches:\n", - "# edge_lens = np.array([dl(i,j) for i,j in zip(branch[:-1], branch[1:])])\n", - "# edge_lens = np.where(edge_lens < min_len, min_len, edge_lens)\n", - "# cum_edge_lens = np.concatenate([[0], edge_lens.cumsum()])\n", - "# local_branch_inds = cum_edge_lens // max_len\n", + "def pandas_to_nx(\n", + " node_attrs: pd.DataFrame, edge_attrs: pd.DataFrame, global_attrs: pd.Series\n", + ") -> nx.DiGraph:\n", + " \"\"\"Convert node_attrs, edge_attrs and global_attrs from pandas datatypes to a NetworkX DiGraph.\n", + "\n", + " Args:\n", + " node_attrs: DataFrame containing node attributes\n", + " edge_attrs: DataFrame containing edge attributes\n", + " global_attrs: Series containing global graph attributes\n", + "\n", + " Returns:\n", + " A directed graph with nodes, edges and global attributes from the input data.\n", + " \"\"\"\n", + " has_edge_attrs = None if edge_attrs.empty else True\n", + " G = nx.from_pandas_edgelist(\n", + " edge_attrs.reset_index(),\n", + " source=\"level_0\",\n", + " target=\"level_1\",\n", + " edge_attr=has_edge_attrs,\n", + " create_using=nx.DiGraph(),\n", + " )\n", + "\n", + " nx.set_node_attributes(G, node_attrs.to_dict(orient=\"index\"))\n", + " G.graph.update(global_attrs.to_dict())\n", + " return G\n", + "\n", + "\n", + "def nx_to_pandas(G: nx.DiGraph) -> Tuple[pd.DataFrame, pd.DataFrame, pd.Series]:\n", + " \"\"\"Convert a NetworkX DiGraph to pandas datatypes.\n", + "\n", + " Args:\n", + " G: Input directed graph\n", + "\n", + " Returns:\n", + " Tuple containing:\n", + " - DataFrame of node attributes\n", + " - DataFrame of edge attributes\n", + " - Series of global graph attributes\n", + " \"\"\"\n", + " edge_df = nx.to_pandas_edgelist(G).set_index([\"source\", \"target\"])\n", + " edge_df.index.names = [None, None]\n", + " node_df = pd.DataFrame.from_dict(dict(G.nodes(data=True)), orient=\"index\")\n", + "\n", + " return node_df, edge_df, pd.Series(G.graph)\n", + "\n", + "\n", + "def swc_to_nx(fname: str, num_lines: Optional[int] = None) -> nx.DiGraph:\n", + " \"\"\"Read a SWC morphology file into a NetworkX DiGraph.\n", + "\n", + " Args:\n", + " fname: Path to the SWC file\n", + " num_lines: Number of lines to read from the file\n", + "\n", + " Returns:\n", + " A directed graph representing the morphology where:\n", + " - Nodes have attributes: id, x, y, z, r (radius)\n", + " - Edges represent parent-child relationships\n", + " \"\"\"\n", + " i_id_xyzr_p = np.loadtxt(fname)[:num_lines]\n", + "\n", + " graph = nx.DiGraph()\n", + " for i, id, x, y, z, r, p in i_id_xyzr_p.tolist(): # tolist: np.float64 -> float\n", + " graph.add_node(int(i), **{\"id\": int(id), \"x\": x, \"y\": y, \"z\": z, \"r\": r})\n", + " if p != -1:\n", + " graph.add_edge(int(p), int(i))\n", + " return graph\n", + "\n", + "\n", + "def nx_to_jax(G: nx.DiGraph) -> jax.tree_util.PyTree:\n", + " \"\"\"Convert a NetworkX DiGraph to a Jax tree.\n", + "\n", + " Args:\n", + " G: Input directed graph\n", + "\n", + " Returns:\n", + " A Jax tree representing the morphology.\n", + " \"\"\"\n", + "\n", + " inds, jax_node_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *G.nodes(data=True))\n", + " jax_node_attrs[\"index\"] = jnp.array(inds)\n", + "\n", + " *inds, jax_edge_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *G.edges(data=True))\n", + " jax_edge_attrs[\"index_pre\"] = jnp.array(inds[0])\n", + " jax_edge_attrs[\"index_post\"] = jnp.array(inds[1])\n", + "\n", + " jax_global_attrs = {k: jnp.array(v) for k, v in G.graph.items()}\n", + "\n", + " return jax_node_attrs, jax_edge_attrs, jax_global_attrs\n", + "\n", + "def jax_to_nx(jax_node_attrs: jax.tree_util.PyTree, jax_edge_attrs: jax.tree_util.PyTree, jax_global_attrs: jax.tree_util.PyTree) -> nx.DiGraph:\n", + " \"\"\"Convert a Jax tree to a NetworkX DiGraph.\n", + "\n", + " Args:\n", + " jax_node_attrs: Jax tree of node attributes\n", + " jax_edge_attrs: Jax tree of edge attributes\n", + " jax_global_attrs: Jax tree of global graph attributes\n", + "\n", + " Returns:\n", + " A NetworkX DiGraph representing the morphology.\n", + " \"\"\"\n", + " node_df, edge_df, global_attrs = jax_to_pandas(jax_node_attrs, jax_edge_attrs, jax_global_attrs)\n", + " return pandas_to_nx(node_df, edge_df, global_attrs)\n", + "\n", + "def jax_to_pandas(jax_node_attrs: jax.tree_util.PyTree, jax_edge_attrs: jax.tree_util.PyTree, jax_global_attrs: jax.tree_util.PyTree) -> Tuple[pd.DataFrame, pd.DataFrame, pd.Series]:\n", + " \"\"\"Convert a Jax tree to pandas datatypes.\n", + "\n", + " Args:\n", + " jax_node_attrs: Jax tree of node attributes\n", + " jax_edge_attrs: Jax tree of edge attributes\n", + " jax_global_attrs: Jax tree of global graph attributes\n", + "\n", + " Returns:\n", + " Tuple containing:\n", + " - DataFrame of node attributes\n", + " - DataFrame of edge attributes\n", + " - Series of global graph attributes\n", + " \"\"\"\n", + "\n", + " node_index = np.array(jax_node_attrs[\"index\"])\n", + " node_attrs_df = pd.DataFrame({k:v.tolist() for k, v in jax_node_attrs.items()}, index=node_index).drop(columns=[\"index\"])\n", " \n", - "# # Find indices where local_branch_inds changes\n", - "# change_points = np.where(np.diff(local_branch_inds) != 0)[0]\n", - "# # Get the edges (pairs of nodes) where the change occurs\n", - "# change_edges = [(branch[i], branch[i+1]) for i in change_points]\n", - "# print(change_edges)\n", - " \n" + " edge_index = pd.MultiIndex.from_arrays(np.vstack([jax_edge_attrs[\"index_pre\"], jax_edge_attrs[\"index_post\"]]))\n", + " edge_attrs_df = pd.DataFrame({k:v.tolist() for k, v in jax_edge_attrs.items()}, index = edge_index).drop(columns=[\"index_pre\", \"index_post\"])\n", + "\n", + " global_attrs_df = pd.Series(jax_global_attrs)\n", + "\n", + " return node_attrs_df, edge_attrs_df, global_attrs_df\n", + "\n", + "def pandas_to_jax(node_df: pd.DataFrame, edge_df: pd.DataFrame, global_attrs: pd.Series) -> jax.tree_util.PyTree:\n", + " \"\"\"Convert pandas datatypes to a Jax tree.\n", + "\n", + " Args:\n", + " node_df: DataFrame of node attributes\n", + " edge_df: DataFrame of edge attributes\n", + " global_attrs: Series of global graph attributes\n", + " \"\"\"\n", + " node_attrs = node_df.to_dict(orient=\"index\")\n", + " edge_attrs = edge_df.to_dict(orient=\"index\")\n", + "\n", + " inds, jax_node_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *node_attrs.items())\n", + " jax_node_attrs[\"index\"] = jnp.array(inds)\n", + "\n", + " *inds, jax_edge_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *edge_attrs.items())\n", + " jax_edge_attrs[\"index_pre\"] = jnp.array(inds[0])\n", + " jax_edge_attrs[\"index_post\"] = jnp.array(inds[1])\n", + "\n", + " jax_global_attrs = {k: jnp.array(v) for k, v in global_attrs.items()}\n", + "\n", + " return jax_node_attrs, jax_edge_attrs, jax_global_attrs\n" ] }, { "cell_type": "code", - "execution_count": 168, + "execution_count": 821, "metadata": {}, "outputs": [], "source": [ - "morph_tree = swc_to_morphtree(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", - "morph_comps = compartmentalize(morph_tree, ncomp=1)\n", - "morph_comps = _add_jaxley_meta_data(morph_comps)\n", - "morph_comps = _replace_branchpoints_with_edges(morph_comps)\n", - "cell = _build_module(morph_comps)" + "class TestModule:\n", + " def __init__(self, node_attrs, edge_attrs, global_attrs):\n", + " self.node_attrs = node_attrs\n", + " self.edge_attrs = edge_attrs\n", + " self.global_attrs = global_attrs\n", + " self._nodes_in_view = jnp.arange(len(node_attrs[\"index\"]))\n", + " self._edges_in_view = jnp.arange(len(edge_attrs[\"index_pre\"]))\n", + " self.base = self\n", + "\n", + " @property\n", + " def _num_nodes(self):\n", + " return len(self.node_attrs[\"index\"])\n", + " \n", + " @property\n", + " def _num_edges(self):\n", + " return len(self.edge_attrs[\"index_pre\"])\n", + "\n", + " def __repr__(self):\n", + " node_keys = list(self.node_attrs.keys())\n", + " edge_keys = list(self.edge_attrs.keys())\n", + " global_keys = list(self.global_attrs.keys())\n", + " return f\"TestModule(node_attrs={self._num_nodes}*{node_keys}, edge_attrs={self._num_edges}*{edge_keys}, global_attrs={global_keys})\"\n", + "\n", + " def select_nodes(self, inds):\n", + " return jax.tree.map(lambda x: x.at[inds].get(), self.node_attrs)\n", + "\n", + " def select_edges(self, inds):\n", + " return jax.tree.map(lambda x: x.at[inds].get(), self.edge_attrs)\n", + "\n", + " def select(self, nodes=None, edges=None):\n", + " self._nodes_in_view = self._nodes_in_view if nodes is None else nodes\n", + " self._edges_in_view = self._edges_in_view if edges is None else edges\n", + " view = TestModule(self.select_nodes(self._nodes_in_view), self.select_edges(self._edges_in_view), self.global_attrs)\n", + " view.base = self\n", + " return view\n", + " \n", + " @property\n", + " def pandas(self):\n", + " return jax_to_pandas(self.node_attrs, self.edge_attrs, self.global_attrs)\n", + " \n", + " @property\n", + " def nodes(self):\n", + " return self.pandas[0]\n", + " \n", + " @property\n", + " def edges(self):\n", + " return self.pandas[1]\n", + " \n", + " @property\n", + " def globals(self):\n", + " return self.pandas[2]\n", + " \n", + " def set(self, key, value):\n", + " if key in self.node_attrs:\n", + " self.base.node_attrs[key] = self.base.node_attrs[key].at[self._nodes_in_view].set(value)\n", + " elif key in self.edge_attrs:\n", + " self.base.edge_attrs[key] = self.base.edge_attrs[key].at[self._edges_in_view].set(value)\n", + " elif key in self.global_attrs:\n", + " self.base.global_attrs[key] = self.base.global_attrs[key].at[:].set(value)\n", + " else:\n", + " raise ValueError(f\"Key {key} not found in any attribute\")\n", + " return TestModule(self.node_attrs, self.edge_attrs, self.global_attrs)\n", + " \n", + " def insert(self, channel):\n", + " self.base.global_attrs[\"channels\"][channel.name] = channel\n", + " for k, v in {**channel.states, **channel.params}.items():\n", + " self.base.node_attrs[k] = jnp.nan*jnp.stack([v]*self._num_nodes, axis=0)\n", + " self.base.node_attrs[k] = self.base.node_attrs[k].at[self._nodes_in_view].set(v)\n", + " return self.base\n", + " \n", + "def connect(pre_view, post_view, synapse):\n", + " pre_view.base.global_attrs[\"synapses\"][synapse.name] = synapse\n", + " for k, v in {**synapse.states, **synapse.params}.items():\n", + " pre_view.base.edge_attrs[k] = jnp.nan*jnp.stack([v]*pre_view._num_edges, axis=0)\n", + " pre_view.base.edge_attrs[k] = pre_view.base.edge_attrs[k].at[pre_view._edges_in_view].set(v)\n", + " return pre_view.base" ] }, { "cell_type": "code", - "execution_count": 171, + "execution_count": 822, "metadata": {}, "outputs": [], "source": [ - "for n, attrs in morph_comps.node_attrs.items():\n", - " attrs[\"test\"] = jnp.ones((1,1))" + "class TestChannel:\n", + " def __init__(self, name=None):\n", + " self.name = name if name is not None else \"TestChannel\"\n", + " self.states = {\"m\": 0.0, \"h\": 0.0}\n", + " self.params = {\"E\": jnp.array([0.0]), \"g\": jnp.array([[0.0, 0.0], [0.0, 0.0]])}\n", + "\n", + "class TestSynapse:\n", + " def __init__(self, name=None):\n", + " self.name = name if name is not None else \"TestSynapse\"\n", + " self.states = {\"g\": 0.0}\n", + " self.params = {\"E\": jnp.array([0.0]), \"g\": jnp.array([0.0])}" ] }, { "cell_type": "code", - "execution_count": 180, + "execution_count": 823, + "metadata": {}, + "outputs": [], + "source": [ + "G = swc_to_nx(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", + "jax_node_attrs, jax_edge_attrs, jax_global_attrs = nx_to_jax(G)\n", + "cell = TestModule(jax_node_attrs, jax_edge_attrs, jax_global_attrs)\n", + "cell.global_attrs[\"channels\"] = {}\n", + "cell.global_attrs[\"synapses\"] = {}" + ] + }, + { + "cell_type": "code", + "execution_count": 825, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'apical': Array([ True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True], dtype=bool),\n", - " 'axial_resistivity': Array([1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,\n", - " 1000., 1000.], dtype=float64),\n", - " 'basal': Array([False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, True, True,\n", - " True, True, True, True, True, True, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False], dtype=bool),\n", - " 'branch_index': Array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n", - " 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n", - " 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\n", - " 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n", - " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,\n", - " 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,\n", - " 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n", - " 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,\n", - " 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,\n", - " 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\n", - " 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,\n", - " 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154], dtype=int64),\n", - " 'capacitance': Array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,\n", - " 1., 1.], dtype=float64),\n", - " 'cell_index': Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", - " 0], dtype=int64),\n", - " 'comp_index': Array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n", - " 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n", - " 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\n", - " 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n", - " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,\n", - " 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,\n", - " 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n", - " 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,\n", - " 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,\n", - " 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\n", - " 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,\n", - " 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154], dtype=int64),\n", - " 'length': Array([2.44227045e+02, 4.27393845e+00, 2.40982169e+02, 4.67513057e+01,\n", - " 8.65335301e+01, 1.71028475e+01, 2.46046913e+01, 5.00520562e+01,\n", - " 5.37613212e+01, 1.59714426e+02, 7.48997041e+01, 1.86023601e+01,\n", - " 1.17733295e+02, 3.48567067e+00, 6.99059144e+01, 4.18909298e+00,\n", - " 1.13682833e+02, 1.63440324e+01, 8.36221267e+01, 7.14833481e+01,\n", - " 5.60078230e+01, 8.65139844e+00, 1.19434577e+01, 1.18341624e+01,\n", - " 6.04821169e+01, 2.22652195e+00, 8.64983664e+01, 1.01865650e+02,\n", - " 1.04995175e+02, 1.81920197e+02, 1.14303517e+02, 1.24831143e+01,\n", - " 8.32100003e+00, 5.84467372e+01, 6.03573930e+01, 7.07951637e+00,\n", - " 7.97070260e+00, 6.54202812e+01, 3.98980463e+01, 4.73884329e+01,\n", - " 1.11205690e+01, 1.58199233e+01, 1.06745317e+01, 1.93803826e+02,\n", - " 4.68279814e+01, 1.16410913e+02, 2.18482129e+01, 3.98674512e+01,\n", - " 1.31019920e+01, 1.14727338e+02, 2.62038740e+01, 2.36348559e+01,\n", - " 1.46372243e+02, 1.77078541e+02, 1.51908215e+02, 1.88632174e+01,\n", - " 1.99484663e+01, 2.01271439e+02, 9.98779052e+01, 7.20884214e+01,\n", - " 1.03907121e+02, 3.36359252e+01, 5.89085479e+01, 1.07287479e+02,\n", - " 7.34204122e+01, 2.08664292e+01, 6.14484518e+01, 7.76717167e+00,\n", - " 3.75958736e+01, 5.98194156e+00, 8.28050749e+01, 5.15007803e+01,\n", - " 7.69670339e+01, 1.38513551e+02, 5.89333860e-01, 7.13845088e+01,\n", - " 2.47290064e+02, 1.03945877e+01, 1.37263347e+02, 2.07062881e+02,\n", - " 8.30791299e+01, 1.37880444e+01, 2.48048336e+01, 2.33607253e+01,\n", - " 1.74379156e+01, 5.70210922e+01, 5.34781853e+01, 7.01609823e+01,\n", - " 1.41706274e+02, 1.99370310e+02, 2.27512040e+02, 1.94238703e+02,\n", - " 5.71602082e+01, 2.87768195e+01, 9.24722613e+01, 2.51768663e+00,\n", - " 8.65304227e+01, 1.82482876e-01, 3.18533866e+01, 6.42759470e+01,\n", - " 1.39461130e+01, 4.02934985e+01, 7.98859607e+01, 1.59913083e+02,\n", - " 2.82131445e+01, 1.00706363e+02, 4.29941742e+01, 2.31970368e+02,\n", - " 5.13527546e+01, 1.50636642e+01, 6.75241154e+01, 6.61563113e+01,\n", - " 1.26906107e+01, 1.76133011e+02, 4.50523713e+01, 2.06259293e+02,\n", - " 1.87169885e+01, 1.47306550e+01, 3.54588338e+01, 1.75242344e+02,\n", - " 1.32771667e+00, 1.29183383e+02, 5.74656307e-01, 1.40209297e+02,\n", - " 1.78636825e+01, 7.75760254e+01, 5.89367355e+01, 1.18174494e+02,\n", - " 7.61007831e+01, 6.06704256e+01, 9.94571441e+01, 9.31158162e+01,\n", - " 1.92990563e+02, 8.83708697e+01, 1.56182708e+02, 2.01756276e+01,\n", - " 4.55395873e+01, 3.14180157e+02, 4.96918789e+01, 1.46905134e+02,\n", - " 1.03873063e+02, 1.42322205e+02, 3.09882545e+01, 3.72726316e+01,\n", - " 6.08114959e+01, 2.70516732e+01, 6.01662185e+01, 8.38092975e+01,\n", - " 4.53456511e+01, 2.19301346e+02, 2.05210304e+02, 9.17689802e+01,\n", - " 7.76761757e+00, 1.27914756e+02, 1.22357698e+02], dtype=float64),\n", - " 'radius': Array([0.24 , 0.4 , 0.24 , 0.4 , 0.24 ,\n", - " 0.4 , 0.24 , 0.4 , 0.24 , 0.57828469,\n", - " 0.24 , 0.79 , 0.4 , 0.87 , 0.24 ,\n", - " 0.87 , 0.24 , 0.87 , 0.24 , 0.87 ,\n", - " 0.4 , 1.10211933, 0.72973568, 1.18 , 0.4 ,\n", - " 1.18 , 0.4 , 1.03 , 0.4 , 1.5 ,\n", - " 0.46888305, 6.36039227, 7.96 , 0.71 , 1.10336459,\n", - " 1.18544992, 0.79 , 0.55 , 0.55 , 0.55 ,\n", - " 0.55 , 0.55 , 0.55 , 0.24 , 0.55 ,\n", - " 0.24 , 0.55 , 0.87 , 0.55 , 0.4 ,\n", - " 0.67599993, 0.55 , 0.55 , 0.4 , 0.24 ,\n", - " 0.55 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", - " 0.4 , 0.4 , 0.4 , 0.4 , 0.24 ,\n", - " 0.55 , 0.4 , 0.55 , 0.55 , 0.55 ,\n", - " 0.55 , 0.55 , 0.475 , 0.4 , 0.55 ,\n", - " 0.87 , 0.4 , 1.34 , 0.43771301, 0.4 ,\n", - " 0.4 , 0.4 , 0.4 , 1.03 , 0.475 ,\n", - " 0.55 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", - " 0.4 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", - " 0.87 , 0.4 , 0.87 , 0.4 , 0.24 ,\n", - " 0.55 , 0.24 , 0.24 , 0.24 , 0.24 ,\n", - " 0.24 , 0.24 , 0.4 , 0.4 , 0.31876093,\n", - " 0.4 , 0.24 , 0.24 , 0.4 , 0.24 ,\n", - " 0.4 , 0.41539049, 0.42840312, 0.4 , 0.4 ,\n", - " 0.4 , 0.4 , 0.4 , 0.24 , 0.24 ,\n", - " 0.24 , 0.24 , 0.24 , 0.24 , 0.4 ,\n", - " 0.4 , 1.18 , 0.55 , 0.55 , 0.4 ,\n", - " 0.4 , 0.4 , 0.24 , 0.4 , 0.4 ,\n", - " 0.24 , 0.4 , 0.4 , 0.4 , 0.4 ,\n", - " 0.4 , 0.24 , 0.24 , 0.24 , 0.24 ,\n", - " 0.24 , 0.24 , 0.24 , 0.24 , 0.4 ], dtype=float64),\n", - " 'soma': Array([False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, True, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False], dtype=bool),\n", - " 'test': Array([[[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]],\n", - " \n", - " [[1.]]], dtype=float64),\n", - " 'v': Array([-70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70., -70., -70., -70., -70., -70., -70., -70., -70., -70., -70.,\n", - " -70.], dtype=float64),\n", - " 'x': Array([-3.88140591e+01, -3.47665895e+01, -4.62851460e+01, -2.86055828e+01,\n", - " -6.04664941e+01, -2.22141373e+01, -2.17649065e+01, -1.46674384e+01,\n", - " -2.65934838e+01, -7.64561829e+00, -5.55926798e+00, -2.19500000e+00,\n", - " -1.62525338e+01, -4.50000000e-02, -8.90751403e+00, 4.35000000e-01,\n", - " 7.77627645e+00, -7.36059522e-01, -1.65841611e+01, 8.14565057e-01,\n", - " 2.13285961e+01, 6.89445123e+00, 4.05295155e+00, 7.38500000e+00,\n", - " 1.67828190e+01, 7.71000000e+00, 2.01344625e+00, 1.08146263e+01,\n", - " 2.52294648e+00, 1.77869711e+01, 2.53586342e+01, 1.96899895e+00,\n", - " -1.43191395e+00, 1.07794505e+01, -3.38124350e+00, -1.10783510e+01,\n", - " -1.35700000e+01, -2.17445329e+01, -2.04646257e+01, -2.40601176e+01,\n", - " -2.73733044e+01, -3.17616719e+01, -3.12286604e+01, -3.46899208e+01,\n", - " -4.09685246e+01, -4.65120057e+01, -3.84031315e+01, -1.34834327e+01,\n", - " -1.73996943e+01, -2.91027177e+01, -1.28358122e+01, -1.45804066e+01,\n", - " -1.11253485e+01, -8.15036285e+00, -2.21252519e+01, -2.70002952e+01,\n", - " -2.46579547e+01, -6.35780453e+01, -4.48365602e+01, -3.92184464e+01,\n", - " -7.13437925e+01, -5.51445682e+01, -6.44816671e+01, -9.35387104e+01,\n", - " -6.91735810e+01, 1.03711686e+01, 1.74618476e+01, 5.43191123e+00,\n", - " 1.19414126e+01, 2.84773808e+00, 1.93901408e+00, 1.93595787e-01,\n", - " 1.29500000e+00, -2.72412240e+01, -5.80263563e+00, 1.46500000e+00,\n", - " 2.22187553e+01, 2.53570369e+00, -1.84266862e+00, 1.51830631e+01,\n", - " 2.20613544e+01, -3.84324259e+00, 1.71926423e+00, -5.57872256e-01,\n", - " -7.05500000e+00, -1.55119060e+01, -4.13728233e+00, -3.67836032e+01,\n", - " -6.20384343e+01, 1.05045409e+01, -2.26490914e+01, 1.32178956e+01,\n", - " 7.66484909e+00, 2.31079088e+01, 1.61021887e+01, 1.46392832e+01,\n", - " 1.10439022e+01, 1.58050000e+01, 1.78764087e+01, 2.12141509e+01,\n", - " 1.89122741e+01, 2.25274810e+01, 3.25100849e+01, 2.20398342e+01,\n", - " 1.89171231e+01, 5.45815165e+01, 5.40631551e+01, 8.34180477e+01,\n", - " 2.02817763e+01, 1.98801349e+01, 1.25974545e+01, 2.77192419e+01,\n", - " 2.20200000e+01, 2.96250976e+01, 3.23790033e+01, 5.64145841e+01,\n", - " 2.72277182e+01, 2.94151398e+01, 2.78960365e+01, 6.50720438e+01,\n", - " 3.15165333e+01, 5.63451453e+01, 3.10089173e+01, 1.77797413e+01,\n", - " 1.11620758e+01, 9.16106710e+00, 9.64909680e+00, 1.29319048e+01,\n", - " -5.55020829e+00, 2.96935061e+01, 2.25534511e+01, 5.56528605e+01,\n", - " 9.99225200e+01, 6.09454728e+01, 2.10102712e+01, 2.17317292e+01,\n", - " 2.82162141e+01, 7.31353939e+01, 4.62060688e+01, 9.44369001e+01,\n", - " 9.65242301e+01, -1.17380615e+01, -9.09180601e+00, -4.08751305e+00,\n", - " -1.72995328e+01, -3.10644853e+01, -4.28129473e+01, 6.47747363e+01,\n", - " 4.36760765e+01, 4.51429852e+01, 2.91750433e+01, -2.49549155e+01,\n", - " -1.26787102e+01, 1.20463251e+01, -7.37012198e+00], dtype=float64),\n", - " 'y': Array([-467.22175756, -399.80279422, -486.5345792 , -387.37532949,\n", - " -414.1453725 , -372.96551637, -377.3156131 , -353.98109982,\n", - " -376.98191136, -303.34552605, -358.39305046, -261.665 ,\n", - " -285.39362573, -254.215 , -266.40405108, -252.16 ,\n", - " -281.71696586, -244.85748401, -260.2859902 , -214.87275928,\n", - " -232.50102171, -183.59455434, -184.05942731, -181.41 ,\n", - " -194.19403766, -179.465 , -192.55559887, -152.12482716,\n", - " -159.71766977, -77.08047503, -135.40164775, -5.83329182,\n", - " 3.88615594, 7.08749238, 8.8679957 , 12.04773412,\n", - " 13.225 , 12.61433384, 25.35064568, 58.31648265,\n", - " 45.93333923, 51.6311146 , 53.87829662, 72.59061764,\n", - " 67.5258203 , 90.24287678, 62.48958086, 17.41335817,\n", - " 16.59322005, 30.47593334, 18.89287553, 25.87304953,\n", - " 34.73637081, 46.83288325, 71.8043282 , 27.79545894,\n", - " 19.7320453 , 106.42462676, 63.67345983, 28.461845 ,\n", - " 13.60008591, 60.41825342, 51.51458261, 103.55194279,\n", - " 97.88617877, 11.693338 , 5.92279773, 11.2442272 ,\n", - " 13.02718082, 13.8047606 , 36.66509591, 21.27139234,\n", - " 13.865 , 82.42212564, 37.49542511, 13.58 ,\n", - " 16.19182246, 13.55030688, 14.24151464, 65.01517003,\n", - " 28.39995684, 24.25018969, 30.79639145, 14.44969604,\n", - " 21.1 , 25.70793736, 38.95245081, 43.61421049,\n", - " 56.63902138, 104.13980011, 128.72752265, 61.24197344,\n", - " 56.74388898, 80.96430726, 100.16385372, 17.57025633,\n", - " 37.5829197 , 17.47 , 19.03547843, 22.4971067 ,\n", - " 17.6838308 , 38.1357177 , 43.22117954, 65.74640932,\n", - " 47.65934149, 71.65161919, 50.48598164, 56.32578249,\n", - " 34.38530483, 54.39253945, 76.57172314, 68.73963285,\n", - " 61.15 , 129.01740518, 80.26277401, 76.98769888,\n", - " 31.4711477 , 44.24275793, 51.97663607, 114.39658219,\n", - " 51.13726417, 121.04355091, 66.35524526, 114.98295441,\n", - " 80.27069362, 108.96831315, 96.68302983, 151.95575124,\n", - " 127.09725403, -2.67126416, 9.57396065, 1.81999783,\n", - " 41.86340217, -208.54174156, -130.79601473, -223.35724107,\n", - " -219.61857652, -327.27298222, -235.51987584, -285.77979536,\n", - " -265.36770569, -209.22123097, -188.67837147, -186.40151314,\n", - " -208.19400105, -238.99450251, -223.94711117, -218.78824582,\n", - " -216.75015638, -461.63075952, -467.24896436, -530.30717898,\n", - " -521.40277554, -433.83064446, -437.11824757], dtype=float64),\n", - " 'z': Array([ 61.14692632, 12.19748436, 27.28 , 25.76 ,\n", - " 11.51407401, 17.97892053, 13.97488458, 9.6433186 ,\n", - " -4.4 , 5.27622108, -4.67527252, 0.76 ,\n", - " 28.87 , 8.565 , -11.25195396, 11.77 ,\n", - " 34.33086009, 8.37256587, 43.27 , -2.23751834,\n", - " 15.07087261, 4.44270864, 6.41105726, 14.395 ,\n", - " 29.76343097, 19.835 , 30.60567925, 5.06034567,\n", - " 35.99978727, 1.84 , 44.08334803, 0. ,\n", - " 0. , 17.28816403, 30.10524862, 58.25343038,\n", - " 51.36 , 48.43476897, 56.67776162, 62.79 ,\n", - " 53.24066087, 60.93608537, 55.97186959, 35.18036425,\n", - " 58.73176729, 53.04 , 57.68 , 41.53315306,\n", - " 53.36 , 26.39211569, 34.5980048 , 31.59748853,\n", - " 25.0789444 , -32.10959913, 17.94486003, 53.10575416,\n", - " 49.45136379, 50.12462076, 31.64510844, 39.82193807,\n", - " 41.37762411, 47.0270826 , 61.04 , 38.71177192,\n", - " 43.42675924, 46.82048985, 37.3824518 , 37.78761858,\n", - " 20.64790945, 42.47678577, 31.10010505, 24.42659665,\n", - " 6.635 , 38.91897803, 12.56 , 3.84 ,\n", - " 19.38012979, 44.71551285, -28.97702095, 53.88555438,\n", - " 46.94412938, 30.79487086, 17.68 , 21.03781985,\n", - " 33.54 , 23.16780124, 23.12 , 14.8 ,\n", - " 22.79895063, 17.89706698, 54.31 , -22.33046626,\n", - " 24.56167616, 8.23 , 5.59 , 26.23 ,\n", - " 30.63 , 26.23 , 41.29887915, 17.00837525,\n", - " 31.40269374, 13.69093954, 29.31746084, 19.04132129,\n", - " 24.5473551 , 25.04 , 15.84 , 10.179687 ,\n", - " 21.76 , 15.44924698, 10.58139591, 18.15 ,\n", - " 15.68 , 5.72997792, 0.91787377, 53.70443838,\n", - " 50.42479344, 54.85576002, 49.55335055, 59.06966685,\n", - " 56.33915476, 58.88 , 56.56 , 34.01003695,\n", - " 30.71 , 58.7655592 , 20.02441116, 15.76 ,\n", - " 16.30609289, 15.59233597, 40.87062569, 39.75 ,\n", - " 33.77031441, 38.62313788, 4.15 , 45.45387938,\n", - " 48.05727869, 39.06053515, 34.91626415, 22.92708681,\n", - " 40.99827221, 36.08 , 20.57528003, 40.79519918,\n", - " 45.52 , 42.24970713, 29.64160623, 36.28412232,\n", - " 37.63106542, 1.95884902, -2.28342966, 26.3779279 ,\n", - " 51.27 , 0.15 , 34.47 ], dtype=float64)}" + "TestModule(node_attrs=2630*['id', 'r', 'x', 'y', 'z', 'index', 'm', 'h', 'E', 'g'], edge_attrs=2629*['index_pre', 'index_post', 'g', 'E'], global_attrs=['channels', 'synapses'])" ] }, - "execution_count": 180, + "execution_count": 825, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "jax.tree_util.tree_map(lambda *args: jnp.array(args), *morph_comps.node_attrs.values())" - ] - }, - { - "cell_type": "code", - "execution_count": 117, - "metadata": {}, - "outputs": [], - "source": [ - "class DummyChannel:\n", - " def __init__(self, name = None):\n", - " self.name = self.__class__.__name__ if name is None else name\n", - " self.params = {f\"gbar_{self.name}\": 1.0, f\"e_{self.name}\": 0.0, f\"nn_weights_{self.name}\": jnp.ones((10, 10))}\n", - " self.states = {f\"m_{self.name}\": 0.5, f\"h_{self.name}\": 0.5}\n", - "\n", - "def tree_insert(tree, inds, channel):\n", - " # TODO: Should Module and MorphTree be separate or the same thing?\n", - " tree.global_attrs[\"channels\"][channel.name] = channel\n", - " for i in inds:\n", - " tree.node_attrs[i].update(channel.params)\n", - " tree.node_attrs[i].update(channel.states)\n", - "\n", - "def tree_set(tree, key, value):\n", - " nodes_df, edge_df = tree.to_pandas()\n", - " # if ... if, since param could be in both nodes and edges\n", - " if key in nodes_df.columns:\n", - " valid = ~nodes_df[key].isna() & ~nodes_df.branchpoint\n", - " nodes_df.loc[valid, key] = value\n", - " if key in edge_df.columns:\n", - " valid = ~edge_df[key].isna() & edge_df.synapse\n", - " edge_df.loc[valid, key] = value\n", - " return MorphTree.from_pandas(nodes_df, edge_df, pd.Series(tree.global_attrs))\n", - "\n", - " # # not vectorized, but allows to modify in place\n", - " # nodes_df, edge_df = tree.to_pandas()\n", - " # if key in nodes_df.columns:\n", - " # for i in tree.node_attrs:\n", - " # if key in tree.node_attrs[i]:\n", - " # tree.node_attrs[i][key] = value\n", - " # if key in edge_df.columns:\n", - " # for i, j in tree.edge_attrs:\n", - " # if key in tree.edge_attrs[(i,j)]:\n", - " # tree.edge_attrs[(i,j)][key] = value\n", - "\n", - "\n", - "#TODO: split/merge similar to equinox\n", - "def merge_trees(trees: List[MorphTree]) -> MorphTree:\n", - " tree = trees[0]\n", - " for t in trees[1:]:\n", - " tree.node_attrs.update(t.node_attrs)\n", - " tree.edge_attrs.update(t.edge_attrs)\n", - " return tree\n", - "\n", - "# def split_tree(tree: MorphTree, nodes: List[int]) -> List[MorphTree]:\n", - "# pass\n", - "\n", - "def tree_to_pytree(tree):\n", - " nodes_df, edge_df = tree.to_pandas()\n", - " jax_nodes, jax_edges = {}, {}\n", - " \n", - " node_data = nodes_df.loc[~nodes_df.branchpoint]\n", - " node_data = node_data.drop(columns=[\"branch\", \"branchpoint\", \"groups\"])\n", - " for key in node_data.columns:\n", - " values = jnp.array(node_data.loc[~node_data[key].isna(), key].to_list())\n", - " jax_nodes[key] = values\n", - "\n", - " edge_data = edge_df.loc[edge_df.synapse]\n", - " edge_data = edge_data.drop(columns=[\"comp_edge\", \"synapse\"])\n", - " for key in edge_data.columns:\n", - " values = jnp.array(edge_data.loc[~edge_data[key].isna(), key].to_list())\n", - " jax_edges[key] = values\n", - " return jax_nodes, jax_edges\n", - "\n", - "def tree_view(tree: MorphTree, nodes: List[int]) -> MorphTree:\n", - " return tree.subgraph(nodes)\n", - "\n", - "class DummySynapse:\n", - " def __init__(self, name = None):\n", - " self.name = self.__class__.__name__ if name is None else name\n", - " self.params = {f\"gbar_{self.name}\": 1.0, f\"e_{self.name}\": 0.0, f\"nn_weights_{self.name}\": jnp.ones((10, 10))}\n", - " self.states = {f\"m_{self.name}\": 0.5, f\"h_{self.name}\": 0.5}\n", - "\n", - "def tree_connect(tree, pre, post, synapse):\n", - " # TODO: map / vectorize this\n", - " tree.global_attrs[\"synapses\"][synapse.name] = synapse\n", - " for i, j in zip(pre, post):\n", - " if (i,j) not in tree.edge_attrs:\n", - " tree.edge_attrs[(i,j)] = {\"comp_edge\": False}\n", - " tree.edge_attrs[i, j][\"synapse\"] = True\n", - " tree.edge_attrs[i, j].update(synapse.params)\n", - " tree.edge_attrs[i, j].update(synapse.states)\n", - "\n", - "\n", - "# There can only be one edge per pair of nodes. (or use MultiDiGraph).\n", - "# This means all synapses need to live in the same edge (i,j)\n", - "# -> treat synapses more like channels, i.e. multiple channels per row in nodes -> multiple synapses per edge.\n", - "# downside cannot connect i and j with the same synapse twice, but can do if one synapse is named differently.\n", - "# think about how to handle if i,j is a comp_edge and also connects via synapses\n", - "\n", - "# TODO: node and edge attrs as list or dict?\n", - "# - pro: one can change node / edge idx without changing touching attrs, since pos of node_idx -> pos node_attr\n", - "# - con: hard to index into node / edge attrs\n", - "\n", - "# TODO: get rid of xyzr in most usecases and use the comp / node xyzrs!? -> simplifies all plotting to networkx!\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 118, - "metadata": {}, - "outputs": [], - "source": [ - "tree_insert(morph_comps, [0, 2], DummyChannel(\"test1\"))\n", - "tree_insert(morph_comps, [0, 2], DummyChannel(\"test2\"))\n", - "\n", - "tree_connect(morph_comps, [0, 1], [3, 2], DummySynapse(\"test1\"))\n", - "tree_connect(morph_comps, [0, 1], [1, 2], DummySynapse(\"test2\"))\n", + "view = cell.select(nodes=jnp.array([1, 2]))\n", + "view.set(\"r\", 20)\n", + "cell.insert(TestChannel())\n", "\n", - "# tree_set(morph_comps, \"gbar_test1\", 123)\n", - "# tree_set(morph_comps, \"gbar_test2\", 123)\n", - "\n", - "# subtree = tree_view(morph_comps, list(range(0,2)))\n", - "# subtree = tree_set(subtree, \"length\", 99.99) # <-- setting on views works\n", - "# morph_comps = merge_trees([morph_comps, subtree])" - ] - }, - { - "cell_type": "code", - "execution_count": 356, - "metadata": {}, - "outputs": [], - "source": [ - "from jaxley.io.graph import build_compartment_graph, to_swc_graph, _trace_branches, _remove_branch_points\n", - "\n", - "testcases = [ \n", - "\"morph_3_types_single_point_soma.swc\",\n", - "\"morph_3_types.swc\",\n", - "\"morph_interrupted_soma.swc\",\n", - "\"morph_soma_both_ends.swc\",\n", - "\"morph_somatic_branchpoint.swc\",\n", - "\"morph_non_somatic_branchpoint.swc\", # no soma!\n", - "\"morph_ca1_n120_single_point_soma.swc\",\n", - "\"morph_ca1_n120.swc\",\n", - "\"morph_l5pc_with_axon.swc\",\n", - "\"morph_allen_485574832.swc\",\n", - "]\n", - "\n", - "jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[-3])\n", - "# jx_comps = build_compartment_graph(jx_graph.copy(), ncomp=1)\n", - "\n", - "morph_tree = swc_to_morph_tree(\"../jaxley/tests/swc_files/\"+testcases[-3])\n", - "morph_comps = compartmentalize(morph_tree, num_comps=1)\n", - "morph_comps = _add_meta_data(morph_comps)" + "connect(cell.select(nodes=jnp.array([1, 2])), cell.select(nodes=jnp.array([3, 4])), TestSynapse())" ] }, { "cell_type": "code", - "execution_count": 244, + "execution_count": 827, "metadata": {}, "outputs": [ { "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
gE
12[0.0][0.0]
852[0.0][0.0]
1412[0.0][0.0]
23[0.0][0.0]
34[0.0][0.0]
............
26252626[0.0][0.0]
26262627[0.0][0.0]
26272628[0.0][0.0]
26282629[0.0][0.0]
26292630[0.0][0.0]
\n", + "

2629 rows × 2 columns

\n", + "
" + ], "text/plain": [ - "0 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", - "1 NaN\n", - "2 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,...\n", - "3 NaN\n", - "4 NaN\n", - " ... \n", - "228 NaN\n", - "229 NaN\n", - "230 NaN\n", - "231 NaN\n", - "232 NaN\n", - "Name: nn_weights_test1, Length: 233, dtype: object" + " g E\n", + "1 2 [0.0] [0.0]\n", + " 852 [0.0] [0.0]\n", + " 1412 [0.0] [0.0]\n", + "2 3 [0.0] [0.0]\n", + "3 4 [0.0] [0.0]\n", + "... ... ...\n", + "2625 2626 [0.0] [0.0]\n", + "2626 2627 [0.0] [0.0]\n", + "2627 2628 [0.0] [0.0]\n", + "2628 2629 [0.0] [0.0]\n", + "2629 2630 [0.0] [0.0]\n", + "\n", + "[2629 rows x 2 columns]" ] }, - "execution_count": 244, + "execution_count": 827, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "morph_comps.to_pandas()[0][\"nn_weights_test1\"]" - ] - }, - { - "cell_type": "code", - "execution_count": 260, - "metadata": {}, - "outputs": [], - "source": [ - "jax_nodes, jax_edges = tree_to_pytree(morph_comps)" + "cell.edges" ] }, { "cell_type": "code", - "execution_count": 1582, + "execution_count": 536, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "testcase morph_3_types_single_point_soma.swc: 1, 1\n", - "testcase morph_3_types.swc: 0, 0\n", - "testcase morph_interrupted_soma.swc: 0, 0\n", - "testcase morph_soma_both_ends.swc: 0, 0\n", - "testcase morph_somatic_branchpoint.swc: 0, 0\n", - "testcase morph_non_somatic_branchpoint.swc: 0, 0\n", - "testcase morph_ca1_n120_single_point_soma.swc: 1, 1\n", - "testcase morph_ca1_n120.swc: 0, 0\n", - "testcase morph_l5pc_with_axon.swc: 0, 0\n", - "testcase morph_allen_485574832.swc: 1, 1\n" - ] + "data": { + "text/plain": [ + "TestModule(node_attrs=3*['id', 'index', 'r', 'x', 'y', 'z'], edge_attrs=2*['index'], global_attrs=[])" + ] + }, + "execution_count": 536, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "from jaxley.io.graph import build_compartment_graph, to_swc_graph, _trace_branches\n", - "\n", - "testcases = [ \n", - "\"morph_3_types_single_point_soma.swc\",\n", - "\"morph_3_types.swc\",\n", - "\"morph_interrupted_soma.swc\",\n", - "\"morph_soma_both_ends.swc\",\n", - "\"morph_somatic_branchpoint.swc\",\n", - "\"morph_non_somatic_branchpoint.swc\", # no soma!\n", - "\"morph_ca1_n120_single_point_soma.swc\",\n", - "\"morph_ca1_n120.swc\",\n", - "\"morph_l5pc_with_axon.swc\",\n", - "\"morph_allen_485574832.swc\",\n", - "]\n", - "\n", - "for i, testcase in enumerate(testcases):\n", - " jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcase)\n", - "\n", - " morph_branches = list_branches(MorphTree.from_nx(jx_graph.copy()))\n", - " morph_branch_nodes = [np.sort(b) for b in morph_branches]\n", - "\n", - " # do jx_trace after morph_traces, since jax_trace modifies the graph\n", - " jx_branches = _trace_branches(jx_graph.copy())[1]\n", - " jx_branch_nodes = [np.sort(np.unique(b[:, :-1])) for b in jx_branches]\n", - " if i in [0,6,9]: # single soma\n", - " jx_branch_nodes = [b-1 for b in jx_branch_nodes]\n", - "\n", - " morph_eq_jx = []\n", - "\n", - " for i, b in enumerate(jx_branch_nodes):\n", - " for j, mb in enumerate(morph_branch_nodes):\n", - " if len(b) == len(mb):\n", - " if np.allclose(b, mb):\n", - " morph_eq_jx.append((i,j))\n", - " break\n", - " if len(morph_eq_jx) > 0:\n", - " diff_morph_branches = [b for i, b in enumerate(morph_branch_nodes) if i not in np.array(morph_eq_jx)[:,1]]\n", - " diff_jx_branches = [b for j, b in enumerate(jx_branch_nodes) if j not in np.array(morph_eq_jx)[:,0]]\n", - " else:\n", - " print(\"No branches are equal\")\n", - " diff_morph_branches = morph_branch_nodes\n", - " diff_jx_branches = jx_branch_nodes\n", - " \n", - " # single soma handled differently and will lead to 1 diff branch\n", - " print(f\"testcase {testcase}: {len(diff_morph_branches)}, {len(diff_jx_branches)}\")" + "cell.select(nodes=jnp.array([0, 1, 2]))" ] }, { @@ -1845,77 +1149,170 @@ "metadata": {}, "outputs": [], "source": [ - "# from jaxley.io.graph import build_compartment_graph, to_swc_graph, _trace_branches\n", - "\n", - "# testcases = [ \n", - "# \"morph_3_types_single_point_soma.swc\",\n", - "# \"morph_3_types.swc\",\n", - "# \"morph_interrupted_soma.swc\",\n", - "# \"morph_soma_both_ends.swc\",\n", - "# \"morph_somatic_branchpoint.swc\",\n", - "# \"morph_non_somatic_branchpoint.swc\", # no soma!\n", - "# \"morph_ca1_n120_single_point_soma.swc\",\n", - "# \"morph_ca1_n120.swc\",\n", - "# \"morph_l5pc_with_axon.swc\",\n", - "# \"morph_allen_485574832.swc\",\n", - "# ]\n", - "\n", - "# jx_graph = to_swc_graph(\"../jaxley/tests/swc_files/\"+testcases[2])\n", - "\n", - "# morph_branches = list_branches(MorphTree.from_nx(jx_graph.copy()))\n", - "# morph_branch_nodes = [np.sort(b) for b in morph_branches]\n", - "\n", - "# # do jx_trace after morph_traces, since jax_trace modifies the graph\n", - "# jx_branches = _trace_branches(jx_graph.copy())[1]\n", - "# jx_branch_nodes = [np.sort(np.unique(b[:, :-1])) for b in jx_branches]\n", - "# # jx_branch_nodes = [b-1 for b in jx_branch_nodes]\n", - "\n", - "\n", - "# morph_eq_jx = []\n", - "\n", - "# for i, b in enumerate(jx_branch_nodes):\n", - "# for j, mb in enumerate(morph_branch_nodes):\n", - "# if len(b) == len(mb):\n", - "# if np.allclose(b, mb):\n", - "# morph_eq_jx.append((i,j))\n", - "# break\n", - "# if len(morph_eq_jx) > 0:\n", - "# diff_morph_branches = [b for i, b in enumerate(morph_branch_nodes) if i not in np.array(morph_eq_jx)[:,1]]\n", - "# diff_jx_branches = [b for j, b in enumerate(jx_branch_nodes) if j not in np.array(morph_eq_jx)[:,0]]\n", - "# else:\n", - "# print(\"No branches are equal\")\n", - "# diff_morph_branches = morph_branch_nodes\n", - "# diff_jx_branches = jx_branch_nodes\n", - "\n", - "# jx_subgraph = jx_graph.subgraph(np.unique(np.hstack(diff_morph_branches)))\n", - "\n", - "# # Get node positions and colors\n", - "# pos = {node: (jx_subgraph.nodes[node]['x'], jx_subgraph.nodes[node]['y']) for node in jx_subgraph.nodes()}\n", - "\n", - "# # Create figure with 1x3 subplots\n", - "# fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n", - "\n", - "# # Plot 1: Node indices\n", - "# node_colors = [jx_subgraph.nodes[node]['id'] for node in jx_subgraph.nodes()]\n", - "# nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='viridis', with_labels=True, ax=axes[0])\n", - "# axes[0].set_title('Node Indices')\n", - "\n", - "# # Plot 2: JX branches\n", - "# node_colors = np.zeros(len(jx_subgraph.nodes()))\n", - "# for i, branch in enumerate(diff_jx_branches):\n", - "# node_colors[np.isin(list(jx_subgraph.nodes()), branch)] = i + 1\n", - "# nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='tab10', with_labels=True, ax=axes[1])\n", - "# axes[1].set_title('JX Branches')\n", - "\n", - "# # Plot 3: Morph branches\n", - "# node_colors = np.zeros(len(jx_subgraph.nodes()))\n", - "# for i, branch in enumerate(diff_morph_branches):\n", - "# node_colors[np.isin(list(jx_subgraph.nodes()), branch)] = i + 1\n", - "# nx.draw(jx_subgraph, pos=pos, node_color=node_colors, cmap='tab10', with_labels=True, ax=axes[2])\n", - "# axes[2].set_title('Morph Branches')\n", - "\n", - "# plt.tight_layout()\n", - "# plt.show()" + "@jax.tree_util.register_dataclass\n", + "@dataclass\n", + "class MorphTree:\n", + " \"\"\"MorphTree is a custom cataclass that holds the node and edge attributes of a morphology.\n", + " \n", + " MorphTree is used to store the node and edge attributes of a morphology / jaxley Module\n", + " as a pytree, to allow for easy manipulation of the Module / morphology parameters \n", + " using jax transformations.\n", + "\n", + " MorphTree also allows for easy conversion to and from pandas DataFrames, and networkx \n", + " DiGraphs, as well as basic convenience functions for plotting and renaming or reordering\n", + " of nodes and edges.\n", + " \"\"\"\n", + " node_attrs: Dict[int, Dict[str, Any]]\n", + " edge_attrs: Dict[Tuple[int, int], Dict[str, Any]]\n", + " global_attrs: Dict[str, Any] = field(default_factory=dict)\n", + "\n", + " @property\n", + " def nodes(self) -> jnp.ndarray:\n", + " \"\"\"Returns the node indices as a jax array.\"\"\"\n", + " return jnp.array(list(self.node_attrs.keys())).astype(int)\n", + "\n", + " @property\n", + " def edges(self) -> jnp.ndarray:\n", + " \"\"\"Returns the edge indices as a jax array.\"\"\"\n", + " return jnp.array(list(self.edge_attrs.keys())).astype(int)\n", + "\n", + " def __repr__(self) -> str:\n", + " n_nodes = len(self.node_attrs)\n", + " n_edges = len(self.edge_attrs)\n", + "\n", + " node_keys = list(next(iter(self.node_attrs.values())).keys())\n", + " if len(self.edge_attrs) > 0:\n", + " edge_keys = list(next(iter(self.edge_attrs.values())).keys())\n", + " else:\n", + " edge_keys = []\n", + "\n", + " node_attrs = node_keys if len(self.node_attrs) > 0 else []\n", + " edge_attrs = edge_keys if len(self.edge_attrs) > 0 else []\n", + " return f\"MorphTree(nodes={n_nodes}*{node_attrs}, edges={n_edges}*{edge_attrs}, global={list(self.global_attrs.keys())})\"\n", + " \n", + " def __iter__(self):\n", + " \"\"\"Allows unpacking of MorphTree as: node_attrs, edge_attrs, global_attrs = *tree\"\"\"\n", + " yield self.node_attrs\n", + " yield self.edge_attrs\n", + " yield self.global_attrs\n", + " \n", + " def node(self, i: int) -> Dict[str, Any]:\n", + " \"\"\"Returns the node attributes for the node with index i.\"\"\"\n", + " return self.node_attrs[i]\n", + " \n", + " def edge(self, i: int, j: int) -> Dict[str, Any]:\n", + " \"\"\"Returns the edge attributes for the edge between nodes i and j.\"\"\"\n", + " return self.edge_attrs[i, j]\n", + " \n", + " def to_nx(self) -> nx.DiGraph:\n", + " \"\"\"Returns the MorphTree as a networkx DiGraph.\"\"\"\n", + " G = nx.DiGraph()\n", + " G.add_nodes_from(self.node_attrs.items())\n", + " G.add_edges_from((i, j, d) for (i, j), d in self.edge_attrs.items())\n", + " G.graph.update(self.global_attrs)\n", + " return G\n", + " \n", + " @staticmethod\n", + " def from_nx(G: nx.DiGraph) -> MorphTree:\n", + " \"\"\"Returns a MorphTree from a networkx DiGraph.\"\"\"\n", + " node_attrs = {n: G.nodes[n] for n in G.nodes}\n", + " edge_attrs = {(i, j): G.edges[i, j] for i, j in G.edges}\n", + " return MorphTree(node_attrs, edge_attrs, G.graph)\n", + " \n", + " def to_pandas(self, return_global_attrs: bool = True) -> Tuple[pd.DataFrame, pd.DataFrame]:\n", + " \"\"\"Returns the MorphTree as a pandas DataFrame.\"\"\"\n", + " node_df = pd.DataFrame(self.node_attrs.values(), index=self.node_attrs.keys())\n", + " edge_df = pd.DataFrame(self.edge_attrs.values(), index=self.edge_attrs.keys())\n", + " edge_index = pd.MultiIndex.from_arrays(np.array(self.edges).T)\n", + " edge_df = edge_df.set_index(edge_index)\n", + "\n", + " if return_global_attrs:\n", + " return node_df, edge_df, pd.Series(self.global_attrs)\n", + " return node_df, edge_df\n", + " \n", + " @staticmethod\n", + " def from_pandas(node_df: pd.DataFrame, edge_df: pd.DataFrame, global_attrs: pd.Series = pd.Series()) -> MorphTree:\n", + " \"\"\"Returns a MorphTree from a pandas DataFrame.\"\"\"\n", + " node_attrs = node_df.to_dict(orient=\"index\")\n", + " edge_attrs = edge_df.to_dict(orient=\"index\")\n", + " return MorphTree(node_attrs, edge_attrs, global_attrs.to_dict())\n", + " \n", + " def plot(self, dims=(0,1), ax: Optional[Axes] = None, **kwargs: Any) -> Axes:\n", + " \"\"\"Uses networkx to plot the MorphTree.\n", + " \n", + " Args:\n", + " dims: Dimensions to plot (0:x, 1:y, 2:z).\n", + " ax: plt.Axes.\n", + " **kwargs: kwargs for networkx.draw.\n", + "\n", + " Returns:\n", + " The Axes object on which the MorphTree was plotted.\n", + " \"\"\"\n", + " G = self.to_nx()\n", + " pos = {}\n", + " dims2axes = {0: \"x\", 1: \"y\", 2: \"z\"}\n", + " for n, attr in G.nodes(data=True):\n", + " if \"x\" in attr: # assume y is also present\n", + " pos[n] = (attr[dims2axes[dims[0]]], attr[dims2axes[dims[1]]])\n", + " \n", + " ax = ax if ax is not None else plt.gca()\n", + " nx.draw(G, pos, with_labels=True, ax=ax, **kwargs)\n", + " return ax\n", + "\n", + " def reindex_nodes(self, mapping: dict) -> MorphTree:\n", + " \"\"\"Reindexes the nodes of the MorphTree according to the mapping dictionary.\n", + " \n", + " Args:\n", + " mapping: A dict mapping the old to new node indices.\n", + "\n", + " Returns:\n", + " A new MorphTree with the nodes reindexed according to the mapping.\n", + " \"\"\"\n", + " new_node_attrs = {mapping[i]: attrs for i, attrs in self.node_attrs.items()}\n", + " \n", + " new_edge_attrs = {}\n", + " for (i, j), attrs in self.edge_attrs.items():\n", + " new_edge_attrs[(mapping[i], mapping[j])] = attrs\n", + " \n", + " return MorphTree(new_node_attrs, new_edge_attrs, self.global_attrs)\n", + " \n", + " def reorder_tree(self, new_order: jnp.ndarray) -> MorphTree:\n", + " \"\"\"Reorders the nodes of the MorphTree according to the new order.\n", + " \n", + " Edges are flipped to ensure they are always in ascending order.\n", + " \n", + " Args:\n", + " new_order: New node order. new_order[i] is the new index of node i.\n", + "\n", + " Returns:\n", + " A new MorphTree with the nodes reordered according to the new order.\n", + " \"\"\"\n", + " # TODO: check this does what I think it does, i.e. change the edge orientation\n", + " # in order of appearance of the nodes in self.nodes.\n", + " edges = np.array(self.edges)\n", + " np_order = np.array(new_order)\n", + " idx_i = np.where(edges[:,0] == np_order[:, None])[0]\n", + " idx_j = np.where(edges[:,1] == np_order[:, None])[0]\n", + " is_descending = ~(idx_i < idx_j)\n", + " for (i,j) in edges[is_descending]:\n", + " print(i,j)\n", + " self.edge_attrs[j, i] = self.edge_attrs.pop((i, j))\n", + " return self\n", + " \n", + " def subgraph(self, nodes: List[int]) -> MorphTree:\n", + " \"\"\"Returns a subset of nodes in the MorphTree.\n", + "\n", + " Edges are only included if both nodes are in the subgraph.\n", + " \n", + " Args:\n", + " nodes: List of node indices to include in the subgraph.\n", + "\n", + " Returns:\n", + " A new MorphTree containing only the specified nodes and their edges.\n", + " \"\"\"\n", + " node_attrs_subset = {i: self.node_attrs[i] for i in nodes}\n", + " edge_attrs_subset = {(i,j): attrs for (i,j), attrs in self.edge_attrs.items() if i in nodes and j in nodes}\n", + " return MorphTree(node_attrs_subset, edge_attrs_subset, self.global_attrs)\n" ] } ], From 4319dfb1ff8329f82145fb3f79b5dfa01bb8b909 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Tue, 15 Jul 2025 17:50:15 +0200 Subject: [PATCH 22/24] wip: figuring out more basic things [skip, ci] --- dev.ipynb | 1003 ++++++++--------------------------------------------- 1 file changed, 148 insertions(+), 855 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index d9893f929..bd174028c 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -42,67 +42,7 @@ "\n", "from typing import Optional, List, Dict, Any, Union, Set, Tuple\n", "from matplotlib.axes import Axes\n", - "from dataclasses import dataclass, field\n", - "\n", - "from jaxley.io.graph import _build_module_scaffold" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# -----------------\n", - "# utility functions\n", - "# -----------------\n", - "\n", - "def compute_xyz(G: nx.DiGraph, length: float = 1.0, spread: float = np.pi/8, spread_decay: float = 0.9, twist: float = 0.0, xy_only: bool = True) -> dict[int, tuple[float, float, float]]:\n", - " \"\"\"Compute xyz coordinates for a tree-like appearance of a networkX graph in 2D or 3D.\n", - " \n", - " Handles branches implicitly since nodes in a branch have 1 child.\n", - "\n", - " Args:\n", - " G: The Graph to compute node xyz coordinates for.\n", - " length: The length of each edge.\n", - " spread: The opening angle at which the edges spread out.\n", - " spread_decay: Multiplicative decay factor for the opening angle / spread.\n", - " twist: Add additional twisting. Means fewer overlapping nodes in 3D projections.\n", - " xy_only: Whether to only compute the xy coordinates and fix the z-coordinate.\n", - "\n", - " Returns:\n", - " A dictionary mapping node indices to xyz coordinates.\n", - " \"\"\"\n", - " # TODO: Replace compute_xyz with this or vice versa, redundant!\n", - " root = next(n for n, d in G.in_degree() if d == 0)\n", - " pos = {root: (0.0, 0.0, 0.0)}\n", - "\n", - " def recurse(node, depth=1, theta=0.0, phi=np.pi/2):\n", - " children = [n for n in G.successors(node) if n not in pos]\n", - " if not children: return\n", - " n = len(children)\n", - " curr_spread = spread * (spread_decay ** (depth - 1))\n", - " x0, y0, z0 = pos[node]\n", - " phi = np.pi/2 if xy_only else phi\n", - " base_theta = theta + depth * twist\n", - " if n == 1:\n", - " thetas, phis = [base_theta], [phi]\n", - " else:\n", - " if xy_only:\n", - " thetas = np.linspace(base_theta - curr_spread/2, base_theta + curr_spread/2, n)\n", - " phis = [phi] * n\n", - " else:\n", - " thetas = np.linspace(base_theta, base_theta + 2 * np.pi, n, endpoint=False)\n", - " phis = [phi - curr_spread] * n\n", - " for th, ph, child in zip(thetas, phis, children):\n", - " x = x0 + length * np.sin(ph) * np.cos(th)\n", - " y = y0 + length * np.sin(ph) * np.sin(th)\n", - " z = z0 + length * np.cos(ph) * (not xy_only)\n", - " pos[child] = (x, y, z)\n", - " recurse(child, depth + 1, th, ph)\n", - "\n", - " recurse(root, theta=0.0, phi=np.pi/2)\n", - " return pos" + "from dataclasses import dataclass, field" ] }, { @@ -110,600 +50,6 @@ "execution_count": 4, "metadata": {}, "outputs": [], - "source": [ - "def pandas_to_nx(\n", - " node_attrs: pd.DataFrame, edge_attrs: pd.DataFrame, global_attrs: pd.Series\n", - ") -> nx.DiGraph:\n", - " \"\"\"Convert node_attrs, edge_attrs and global_attrs from pandas datatypes to a NetworkX DiGraph.\n", - "\n", - " Args:\n", - " node_attrs: DataFrame containing node attributes\n", - " edge_attrs: DataFrame containing edge attributes\n", - " global_attrs: Series containing global graph attributes\n", - "\n", - " Returns:\n", - " A directed graph with nodes, edges and global attributes from the input data.\n", - " \"\"\"\n", - " G = nx.from_pandas_edgelist(\n", - " edge_attrs.reset_index(),\n", - " source=\"level_0\",\n", - " target=\"level_1\",\n", - " edge_attr=True,\n", - " create_using=nx.DiGraph(),\n", - " )\n", - "\n", - " nx.set_node_attributes(G, node_attrs.to_dict(orient=\"index\"))\n", - " G.graph.update(global_attrs.to_dict())\n", - " return G\n", - "\n", - "\n", - "def nx_to_pandas(G: nx.DiGraph) -> Tuple[pd.DataFrame, pd.DataFrame, pd.Series]:\n", - " \"\"\"Convert a NetworkX DiGraph to pandas datatypes.\n", - "\n", - " Args:\n", - " G: Input directed graph\n", - "\n", - " Returns:\n", - " Tuple containing:\n", - " - DataFrame of node attributes\n", - " - DataFrame of edge attributes\n", - " - Series of global graph attributes\n", - " \"\"\"\n", - " edge_df = nx.to_pandas_edgelist(G).set_index([\"source\", \"target\"])\n", - " edge_df.index.names = [None, None]\n", - " node_df = pd.DataFrame.from_dict(dict(G.nodes(data=True)), orient=\"index\")\n", - "\n", - " return node_df, edge_df, pd.Series(G.graph)\n", - "\n", - "\n", - "def swc_to_nx(fname: str, num_lines: Optional[int] = None) -> nx.DiGraph:\n", - " \"\"\"Read a SWC morphology file into a NetworkX DiGraph.\n", - "\n", - " Args:\n", - " fname: Path to the SWC file\n", - " num_lines: Number of lines to read from the file\n", - "\n", - " Returns:\n", - " A directed graph representing the morphology where:\n", - " - Nodes have attributes: id, x, y, z, r (radius)\n", - " - Edges represent parent-child relationships\n", - " \"\"\"\n", - " i_id_xyzr_p = np.loadtxt(fname)[:num_lines]\n", - "\n", - " graph = nx.DiGraph()\n", - " for i, id, x, y, z, r, p in i_id_xyzr_p.tolist(): # tolist: np.float64 -> float\n", - " graph.add_node(int(i), **{\"id\": int(id), \"x\": x, \"y\": y, \"z\": z, \"r\": r})\n", - " if p != -1:\n", - " graph.add_edge(int(p), int(i))\n", - " return graph\n", - "\n", - "\n", - "def _split_branches(\n", - " branches: list[list[int]], split_edges: list[tuple[int, int]]\n", - ") -> list[list[int]]:\n", - " \"\"\"Split branches at the given edges.\n", - "\n", - " Args:\n", - " branches: List of branches, each represented as list of nodes.\n", - " split_edges: List of edges between nodes where tracing is discontinous.\n", - "\n", - " Returns:\n", - " An updated list of branches.\n", - " \"\"\"\n", - " for p, n in split_edges:\n", - " for i, branch in enumerate(branches):\n", - " if n in branch:\n", - " split_idx = branch.index(n)\n", - " branches[i : i + 1] = [branch[:split_idx], branch[split_idx:]]\n", - " break\n", - " return branches\n", - "\n", - "\n", - "def _find_swc_tracing_interruptions(G: nx.DiGraph) -> list[tuple[int, int]]:\n", - " \"\"\"Identify discontinuities in the swc tracing order.\n", - "\n", - " Some swc files contain artefacts, where tracing of the same neurite was done\n", - " in disconnected pieces. NEURON swc reader introduce a break in the trace at these\n", - " points, since they parse the file in order. This leads to split branches, which\n", - " should be one. This function identifies these points in the graph.\n", - "\n", - " Example swc file:\n", - " # branch 1\n", - " 1 1 0.0 0.0 0.0 1.0 -1\n", - " 2 1 1.0 0.0 0.0 1.0 1\n", - " 3 1 2.0 0.0 0.0 1.0 2\n", - " # branch 2\n", - " 4 2 3.0 1.0 0.0 1.0 3\n", - " 5 2 4.0 2.0 0.0 1.0 4\n", - " # branch 3\n", - " 6 3 3.0 -1.0 0.0 1.0 3\n", - " 7 3 4.0 -2.0 0.0 1.0 6\n", - " 8 3 5.0 -3.0 0.0 1.0 7\n", - " # ammend branch 2\n", - " 9 4 5.0 3.0 0.0 1.0 5\n", - "\n", - " Args:\n", - " G: NetworkX graph tracing of swc file.\n", - "\n", - " Returns:\n", - " An array of edges where tracing is discontinous.\n", - " \"\"\"\n", - " degree_is_2 = lambda n: G.out_degree(n) + G.in_degree(n) == 2\n", - "\n", - " interrupt_edges = []\n", - " for n in G.nodes:\n", - " if len(parents := list(G.predecessors(n))) > 0:\n", - " p = parents[0]\n", - " if p != n - 1 and degree_is_2(n) and degree_is_2(p):\n", - " interrupt_edges.append((p, n))\n", - " return interrupt_edges\n", - "\n", - "\n", - "def list_branches(\n", - " G,\n", - " return_branchpoints: bool = False,\n", - " ignore_swc_tracing_interruptions=True,\n", - " relevant_ids: List[int] = [1, 2, 3, 4],\n", - " max_len: Optional[float] = None,\n", - ") -> Union[List[List[int]], Tuple[List[List[int]], Set[int], List[Tuple[int, int]]]]:\n", - " \"\"\"Get all uninterrupted paths in the traced morphology (i.e. branches).\n", - "\n", - " The graph is traversed depth-first starting from the first found leaf node.\n", - " Nodes are considered to be part of a branch if they have only one parent and one\n", - " child, which are both of the same type (i.e. have the same `id`). Nodes which are\n", - " branchpoints or leafs are considered start / end points of a branch. A branchpoint\n", - " can start multiple branches.\n", - "\n", - " Args:\n", - " G: NetworkX graph tracing of swc file.\n", - " return_branchpoints: Whether to return the branchpoints and edges between them\n", - " seperately.\n", - " ignore_swc_tracing_interruptions: Whether to ignore discontinuities in the swc\n", - " tracing order. If False, this will result in split branches at these points.\n", - " relevant_ids: All type ids that are not in this list will be ignored for\n", - " tracing the morphology. This means that branches which have multiple type\n", - " ids (which are not in `relevant_ids`) will be considered as one branch.\n", - " Defaults to `[1, 2, 3, 4]`.\n", - "\n", - " Returns:\n", - " A list of linear paths in the graph. Each path is represented as list of nodes.\n", - " \"\"\"\n", - " G = G.to_undirected()\n", - " branches = []\n", - " branchpoints = set()\n", - " visited = set()\n", - "\n", - " was_visited = lambda n1, n2: (n1, n2) in visited or (n2, n1) in visited\n", - " id_of = lambda n: G.nodes[n][\"id\"]\n", - " is_soma = lambda n: id_of(n) == 1\n", - " soma_nodes = lambda: [i for i, n in G.nodes.items() if n[\"id\"] == 1]\n", - "\n", - " def is_branchpoint_or_tip(n: int) -> bool:\n", - " if G.degree(n) == 2:\n", - " i, j = G.neighbors(n)\n", - " # trace dir matters here! For segment with node IDs: [1, 1, 2, 2]\n", - " # -> [[1,1], [1,2,2]]\n", - " # <- [[2,2], [2,1,1]]\n", - " return not same_id(n, j)\n", - "\n", - " is_leaf = G.degree(n) <= 1\n", - " is_branching = G.degree(n) > 2\n", - " return is_leaf or is_branching\n", - "\n", - " def same_id(n1: int, n2: int) -> bool:\n", - " has_id = lambda n: id_of(n) in relevant_ids if \"id\" in G.nodes[n] else False\n", - " if has_id(n1) and has_id(n2):\n", - " return id_of(n1) == id_of(n2)\n", - " return True\n", - "\n", - " def walk_path(start: int, succ: int) -> List[int]:\n", - " \"\"\"Walk from start to succ, recording new nodes until a branching node is hit.\"\"\"\n", - " path = [start, succ]\n", - " visited.add((start, succ))\n", - "\n", - " while G.degree(succ) == 2:\n", - " next_node = next(n for n in G.neighbors(succ) if n != path[-2])\n", - "\n", - " if was_visited(succ, next_node) or is_branchpoint_or_tip(succ):\n", - " break\n", - "\n", - " path.append(next_node)\n", - " visited.add((succ, next_node))\n", - " succ = next_node\n", - "\n", - " return path\n", - "\n", - " leaf = next(n for n in G.nodes if G.degree(n) == 1)\n", - " single_soma = len(soma_nodes()) == 1\n", - " for node in nx.dfs_tree(G, leaf):\n", - " if single_soma and is_soma(node):\n", - " branches.append([node])\n", - "\n", - " elif is_branchpoint_or_tip(node):\n", - " branchpoints.add(node)\n", - " for succ in G.neighbors(node):\n", - " if not was_visited(node, succ):\n", - " branches.append(walk_path(node, succ))\n", - "\n", - " # split branches\n", - " if not ignore_swc_tracing_interruptions: # TODO: fix!\n", - " split_edges = _find_swc_tracing_interruptions(G)\n", - " branches = _split_branches(branches, split_edges)\n", - " branchpoints.update(set(p for (p, n) in split_edges))\n", - "\n", - " # TODO: add max_len\n", - " if max_len is not None:\n", - " raise NotImplementedError(\"max_len not implemented\")\n", - "\n", - " if return_branchpoints:\n", - " branchpoint_edges = sum([list(G.edges(n)) for n in branchpoints], [])\n", - " return branches, branchpoints, branchpoint_edges\n", - " return branches\n", - "\n", - "\n", - "def _add_missing_swc_attrs(G) -> nx.DiGraph:\n", - " \"\"\"Add missing swc attributes to a SWC graph.\n", - "\n", - " Allows to specify morphology from just edges.\n", - "\n", - " Args:\n", - " G: The SWC graph to add missing attributes to.\n", - "\n", - " Returns:\n", - " The SWC graph with missing attributes set to their defaults.\n", - " \"\"\"\n", - " defaults = {\"id\": 0, \"r\": 1}\n", - "\n", - " available_keys = G.nodes[next(iter(G.nodes()))].keys()\n", - " xyz = compute_xyz(G) if \"x\" not in available_keys else {}\n", - " for n, (x, y, z) in xyz.items():\n", - " G.nodes[n][\"x\"] = x\n", - " G.nodes[n][\"y\"] = y\n", - " G.nodes[n][\"z\"] = z\n", - "\n", - " for key in set(defaults.keys()).difference(available_keys):\n", - " nx.set_node_attributes(G, defaults[key], key)\n", - " return G\n", - "\n", - "\n", - "def compartmentalize(\n", - " swc_graph: nx.DiGraph,\n", - " ncomp: int = 1,\n", - " min_radius: Optional[float] = None,\n", - " max_len: Optional[float] = None,\n", - " ignore_swc_tracing_interruptions: bool = True,\n", - " relevant_type_ids: List[int] = [1, 2, 3, 4],\n", - ") -> nx.DiGraph:\n", - " \"\"\"Return a networkX graph that indicates the compartment structure.\n", - "\n", - " Build a new graph made up of compartments in every branch. These compartments are\n", - " spaced at equidistant points along the branch. Node attributes, like radius are\n", - " linearly interpolated along its length.\n", - "\n", - " Example: 4 compartments | edges = - | nodes = o | comp_nodes = x\n", - " o-----------o----------o---o---o---o--------o\n", - " o-------x---o----x-----o--xo---o---ox-------o\n", - "\n", - " This function returns a nx:DiGraph. The graph is directed only because every\n", - " compartment tracks the xyzr coordinates of the associated SWC file. These xyzr\n", - " coordinates are ordered by the order of the traversal of the swc_graph. In later\n", - " methods (e.g. build_solve_graph), we traverse the `comp_graph` and mostly ignore\n", - " the directionality of the edges, but we only use the directionality to reverse the\n", - " xyzr coordinates if necessary.\n", - "\n", - " Args:\n", - " swc_graph: Graph generated by `to_swc_graph()`.\n", - " ncomp: How many compartments per branch to insert.\n", - " root: The root branch from which to start tracing the nodes. This defines the\n", - " branch indices.\n", - " min_radius: Minimal radius for each compartment.\n", - " max_len: Maximal length for each branch. Longer branches are split into\n", - " separate branches.\n", - " ignore_swc_tracing_interruptions: If `False`, it this function automatically\n", - " starts a new branch when a section is traced with interruptions.\n", - " relevant_type_ids: All type ids that are not in this list will be ignored for\n", - " tracing the morphology. This means that branches which have multiple type\n", - " ids (which are not in `relevant_type_ids`) will be considered as one branch.\n", - " If `None`, we default to `[1, 2, 3, 4]`.\n", - "\n", - " Returns:\n", - " Graph of the compartmentalized morphology.\n", - "\n", - " Example usage\n", - " ^^^^^^^^^^^^^\n", - "\n", - " ::\n", - "\n", - " from jaxley.io.graph swc_to_nx\n", - " swc_graph = swc_to_nx(\"path_to_swc.swc\")\n", - " comp_graph = compartmentalize(swc_graph, ncomp=1)\n", - " \"\"\"\n", - " G = _add_missing_swc_attrs(swc_graph)\n", - "\n", - " branches = list_branches(\n", - " G,\n", - " ignore_swc_tracing_interruptions=ignore_swc_tracing_interruptions,\n", - " max_len=max_len,\n", - " relevant_ids=relevant_type_ids,\n", - " )\n", - " nodes_df = nx_to_pandas(G)[0].astype(float)\n", - "\n", - " # create new set of indices which arent already used as node indices to label comps\n", - " existing_inds = set(nodes_df.index)\n", - " num_new_inds = len(branches) * ncomp\n", - " proposed_inds = set(range(num_new_inds + len(existing_inds)))\n", - " proposed_comp_inds = list(\n", - " proposed_inds - existing_inds\n", - " ) # avoid overlap w. node indices\n", - "\n", - " # identify tip nodes (degree == 1 -> node appears only once in edges)\n", - " nodes_in_edges, node_counts_in_edges = np.unique(G.edges, return_counts=True)\n", - " tip_node_inds = nodes_in_edges[node_counts_in_edges == 1]\n", - "\n", - " # collect comps and comp_edges\n", - " branch_nodes, branch_edges = [], []\n", - " xyzr = []\n", - " for i, branch in enumerate(branches):\n", - " node_attrs = nodes_df.loc[branch]\n", - " xyzr_i = node_attrs[[\"x\", \"y\", \"z\", \"r\"]]\n", - " xyzr.append(xyzr_i.values)\n", - "\n", - " compute_edge_lens = lambda x: (x.diff(axis=0).fillna(0) ** 2).sum(axis=1) ** 0.5\n", - " edge_lens = compute_edge_lens(xyzr_i[[\"x\", \"y\", \"z\"]])\n", - " node_attrs[\"l\"] = edge_lens.cumsum() # path length\n", - "\n", - " # For single-point somatata, we set l = 2*r this ensures\n", - " # A_cylinder = 2*pi*r*l = 4*pi*r^2 = A_sphere.\n", - " if len(branch) == 1:\n", - " node_attrs = node_attrs.loc[branch * 2] # duplicate soma node\n", - " radius = node_attrs[\"r\"].iloc[0]\n", - " node_attrs[\"l\"] = np.array([0, 2 * radius])\n", - "\n", - " branch_id = node_attrs[\"id\"].iloc[\n", - " -1\n", - " ] # TODO: how to handle mult. ids in branch!\n", - " branch_len = max(node_attrs[\"l\"])\n", - " comp_len = branch_len / ncomp\n", - " comp_locs = list(np.linspace(comp_len / 2, branch_len - comp_len / 2, ncomp))\n", - "\n", - " # Create node indices and attributes\n", - " # branch_inds, branchpoint, comp_id, comp_len\n", - " branch_tips = branch[0], branch[-1]\n", - " branch_tip_attrs = [\n", - " [i, True, node_attrs[\"id\"].iloc[0], 0],\n", - " [i, True, node_attrs[\"id\"].iloc[-1], 0],\n", - " ]\n", - " comp_attrs = [[i, False, branch_id, comp_len]] * ncomp\n", - "\n", - " comp_inds = proposed_comp_inds[i * ncomp : (i + 1) * ncomp]\n", - " comp_inds = np.array([branch_tips[0], *comp_inds, branch_tips[1]])\n", - " comp_attrs = [branch_tip_attrs[0]] + comp_attrs + [branch_tip_attrs[1]]\n", - " comp_attrs = np.hstack([comp_inds[:, None], comp_attrs])\n", - "\n", - " x = np.array([0] + comp_locs + [branch_len])\n", - " xp = np.array(node_attrs[\"l\"].values)\n", - " fp = np.array(xyzr_i.values)\n", - "\n", - " # TODO: interpolate **r** differently!\n", - " interpolated_coords = np.column_stack(\n", - " [np.interp(x, xp, fp[:, i]) for i in range(fp.shape[1])]\n", - " )\n", - "\n", - " # Combine interpolated coordinates with existing attributes\n", - " comp_attrs = np.hstack([comp_attrs, interpolated_coords])\n", - "\n", - " # remove tip nodes\n", - " comp_attrs = comp_attrs[1:] if branch_tips[0] in tip_node_inds else comp_attrs\n", - " comp_attrs = comp_attrs[:-1] if branch_tips[1] in tip_node_inds else comp_attrs\n", - "\n", - " # Store edges and nodes\n", - " branch_edges.append(list(zip(comp_attrs[:-1, 0], comp_attrs[1:, 0])))\n", - " branch_nodes.append(comp_attrs)\n", - "\n", - " branch_nodes = np.concatenate(branch_nodes)\n", - " comp_attrs_keys = [\"idx\", \"branch\", \"branchpoint\", \"id\", \"l\", \"x\", \"y\", \"z\", \"r\"]\n", - " comp_df = pd.DataFrame(branch_nodes, columns=comp_attrs_keys)\n", - "\n", - " int_cols = [\"idx\", \"branch\", \"id\"]\n", - " comp_df[int_cols] = comp_df[int_cols].astype(int)\n", - "\n", - " bool_cols = [\"branchpoint\"]\n", - " comp_df[bool_cols] = comp_df[bool_cols].astype(bool)\n", - "\n", - " # threshold radius\n", - " if min_radius is not None:\n", - " comp_df[\"r\"] = np.maximum(comp_df[\"r\"], min_radius)\n", - "\n", - " # drop duplicated branch nodes\n", - " comp_df = comp_df.drop_duplicates(subset=[\"idx\"])\n", - " comp_df = comp_df.set_index(\"idx\")\n", - "\n", - " # create comp edges\n", - " comp_edges = sum(branch_edges, [])\n", - " comp_edges_df = pd.DataFrame(index=pd.MultiIndex.from_tuples(comp_edges))\n", - " comp_edges_df[\"synapse\"] = False\n", - " comp_edges_df[\"comp_edge\"] = True\n", - "\n", - " global_attrs = pd.Series({\"xyzr\": xyzr})\n", - " G = pandas_to_nx(comp_df, comp_edges_df, global_attrs)\n", - " G = nx.relabel_nodes(G, {n: i for i, n in enumerate(G.nodes)})\n", - " return G\n", - "\n", - "\n", - "def _add_jaxley_meta_data(G: nx.DiGraph) -> nx.DiGraph:\n", - " \"\"\"Add attributes to and rename existing attributes of the compartalized morphology.\n", - "\n", - " Makes the imported and compartmentalized morphology compatible with jaxley.\n", - " \"\"\"\n", - " nodes_df, edge_df, global_attrs = nx_to_pandas(G)\n", - " module_global_attrs = pd.Series({\"channels\": {}, \"synapses\": {}, \"group_names\": []})\n", - " global_attrs = pd.concat([global_attrs, module_global_attrs])\n", - "\n", - " # rename/reformat existing columns\n", - " group_ids = {0: \"undefined\", 1: \"soma\", 2: \"axon\", 3: \"basal\", 4: \"apical\"}\n", - " for group_id, group_name in group_ids.items():\n", - " where_group = nodes_df[\"id\"] == group_id\n", - " if where_group.any():\n", - " global_attrs[\"group_names\"].append(group_name)\n", - " nodes_df[group_name] = where_group\n", - " nodes_df = nodes_df.drop(columns=[\"id\"])\n", - " module_col_names = {\"r\": \"radius\", \"l\": \"length\", \"branch\": \"branch_index\"}\n", - " nodes_df = nodes_df.rename(module_col_names, axis=1)\n", - "\n", - " # new columns\n", - " nodes_df[\"capacitance\"] = 1.0\n", - " nodes_df[\"v\"] = -70.0\n", - " nodes_df[\"axial_resistivity\"] = 1000.0\n", - " # TODO: rename to cell_index > cell, comp_index > comp, branch_index > branch\n", - " nodes_df[\"comp_index\"] = np.arange(len(nodes_df))\n", - " nodes_df[\"cell_index\"] = 0\n", - "\n", - " return pandas_to_nx(nodes_df, edge_df, global_attrs)\n", - "\n", - "\n", - "def _replace_branchpoints_with_edges(G: nx.DiGraph) -> nx.DiGraph:\n", - " \"\"\"Replace branchpoint nodes with edges connecting parent and children.\"\"\"\n", - " G.add_edges_from([(i, j, {\"branch_edge\": False}) for i, j in G.edges])\n", - " branch_edge_attrs = {\"comp_edge\": True, \"synapse\": False, \"branch_edge\": True}\n", - "\n", - " branchpoints = [n for n in G.nodes if G.nodes[n][\"branchpoint\"]]\n", - " for n in branchpoints:\n", - " parent = next(G.predecessors(n))\n", - " children = list(G.successors(n))\n", - "\n", - " # remove branchpoint and connect parent to children\n", - " G.remove_node(n)\n", - " G.add_edges_from([(parent, c) for c in children], **branch_edge_attrs)\n", - "\n", - " for i, n in enumerate(G.nodes):\n", - " G.nodes[n].pop(\"branchpoint\")\n", - " # TODO: Can we skip relabeling comps and reindexing the dataframe?\n", - " G.nodes[n][\"comp_index\"] = i\n", - " G = nx.relabel_nodes(G, {n: i for i, n in enumerate(G.nodes)})\n", - "\n", - " return G\n", - "\n", - "\n", - "def _compute_branch_parents(\n", - " node_df: pd.DataFrame, edge_df: pd.DataFrame\n", - ") -> List[List[int]]:\n", - " \"\"\"Compute the parent structure of the branch graph (for each cell).\n", - "\n", - " Args:\n", - " node_df: The node dataframe of the graph.\n", - " edge_df: The edge dataframe of the graph.\n", - "\n", - " Returns:\n", - " The parent structure of the branch graph for each cell.\n", - " \"\"\"\n", - " branch_edge_inds = edge_df.index[edge_df[\"branch_edge\"]]\n", - " parent_inds = branch_edge_inds.get_level_values(0)\n", - " child_inds = branch_edge_inds.get_level_values(1)\n", - "\n", - " branch_edges = pd.DataFrame(\n", - " {\n", - " \"parent_branch\": node_df[\"branch_index\"].loc[parent_inds].values,\n", - " \"child_branch\": node_df[\"branch_index\"].loc[child_inds].values,\n", - " }\n", - " )\n", - "\n", - " acc_parents = []\n", - " parent_branch_inds = branch_edges.set_index(\"child_branch\").sort_index()[\n", - " \"parent_branch\"\n", - " ]\n", - "\n", - " for branch_inds in node_df.groupby(\"cell_index\")[\"branch_index\"].unique():\n", - " root_branch_idx = branch_inds[0]\n", - " parents = parent_branch_inds.loc[branch_inds[1:]] - root_branch_idx\n", - " acc_parents.append([-1] + parents.tolist())\n", - " return acc_parents\n", - "\n", - "\n", - "def _build_module(G: nx.DiGraph) -> jx.Module:\n", - " \"\"\"Build a Module from a compartmentalized morphology.\n", - "\n", - " This function builds a Module from a nx.DiGraph that has been compartmentalized.\n", - "\n", - " Args:\n", - " G: The graph to build the Module from.\n", - "\n", - " Returns:\n", - " The Module built from the graph.\n", - " \"\"\"\n", - " node_df, edge_df, global_attrs = nx_to_pandas(G)\n", - "\n", - " nodes_per_branch = node_df[\"branch_index\"].value_counts()\n", - " assert (\n", - " nodes_per_branch.nunique() == 1\n", - " ), \"`from_graph()` does not support a varying number of compartments in each branch.\"\n", - "\n", - " acc_parents = _compute_branch_parents(node_df, edge_df)\n", - " module = _build_module_scaffold(\n", - " node_df, parent_branches=acc_parents, xyzr=global_attrs[\"xyzr\"]\n", - " )\n", - "\n", - " node_df.columns = [\n", - " \"global_\" + col if \"local\" not in col and \"index\" in col else col\n", - " for col in node_df.columns\n", - " ]\n", - "\n", - " synapse_edges = edge_df[edge_df.synapse]\n", - "\n", - " # set column-wise. preserves cols not in df.\n", - " module.nodes[node_df.columns] = node_df\n", - " module.edges = synapse_edges if not synapse_edges.empty else module.edges\n", - "\n", - " # add all the extra attrs\n", - " module.synapses = global_attrs[\"synapses\"]\n", - " module.channels = global_attrs[\"channels\"]\n", - " module.group_names = global_attrs[\"group_names\"]\n", - " module.membrane_current_names = [c.current_name for c in module.channels]\n", - " module.synapse_names = [s._name for s in module.synapses]\n", - "\n", - " return module\n", - "\n", - "\n", - "def nx_to_module(swc_graph: nx.DiGraph, ncomp: int = 1) -> jx.Module:\n", - " comp_graph = compartmentalize(swc_graph, ncomp=ncomp)\n", - " comp_graph = _add_jaxley_meta_data(comp_graph)\n", - " solve_graph = _replace_branchpoints_with_edges(comp_graph)\n", - " module = _build_module(solve_graph)\n", - " return module\n", - "\n", - "\n", - "def read_swc(fname: str) -> jx.Module:\n", - " swc_graph = swc_to_nx(fname)\n", - " return nx_to_module(swc_graph)\n", - "\n", - "\n", - "# def module_to_nx(module: jx.Module) -> nx.DiGraph:\n", - "# global_attrs = {}\n", - "# global_attrs[\"group_names\"] = module.group_names\n", - "# global_attrs[\"synapses\"] = module.synapses\n", - "# global_attrs[\"channels\"] = module.channels\n", - "\n", - "# node_attrs = module.nodes\n", - "# edge_attrs = module.edges\n", - "\n", - "# node_attrs = node_attrs.drop(columns=[col for col in node_attrs.columns if col.startswith(\"local_\")])\n", - "\n", - "# return pandas_to_nx(node_attrs, edge_attrs, global_attrs)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "cell = read_swc(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")" - ] - }, - { - "cell_type": "code", - "execution_count": 811, - "metadata": {}, - "outputs": [], "source": [ "def pandas_to_nx(\n", " node_attrs: pd.DataFrame, edge_attrs: pd.DataFrame, global_attrs: pd.Series\n", @@ -823,8 +169,8 @@ " - Series of global graph attributes\n", " \"\"\"\n", "\n", - " node_index = np.array(jax_node_attrs[\"index\"])\n", - " node_attrs_df = pd.DataFrame({k:v.tolist() for k, v in jax_node_attrs.items()}, index=node_index).drop(columns=[\"index\"])\n", + " node_index = np.array(jax_node_attrs[(\"index\",)])\n", + " node_attrs_df = pd.DataFrame({k:v.tolist() for k, v in jax_node_attrs.items()}, index=node_index).drop(columns=[(\"index\",)])\n", " \n", " edge_index = pd.MultiIndex.from_arrays(np.vstack([jax_edge_attrs[\"index_pre\"], jax_edge_attrs[\"index_post\"]]))\n", " edge_attrs_df = pd.DataFrame({k:v.tolist() for k, v in jax_edge_attrs.items()}, index = edge_index).drop(columns=[\"index_pre\", \"index_post\"])\n", @@ -845,7 +191,7 @@ " edge_attrs = edge_df.to_dict(orient=\"index\")\n", "\n", " inds, jax_node_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *node_attrs.items())\n", - " jax_node_attrs[\"index\"] = jnp.array(inds)\n", + " jax_node_attrs[(\"index\", )] = jnp.array(inds)\n", "\n", " *inds, jax_edge_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *edge_attrs.items())\n", " jax_edge_attrs[\"index_pre\"] = jnp.array(inds[0])\n", @@ -853,31 +199,55 @@ "\n", " jax_global_attrs = {k: jnp.array(v) for k, v in global_attrs.items()}\n", "\n", - " return jax_node_attrs, jax_edge_attrs, jax_global_attrs\n" + " return jax_node_attrs, jax_edge_attrs, jax_global_attrs" ] }, { "cell_type": "code", - "execution_count": 821, + "execution_count": 94, "metadata": {}, "outputs": [], "source": [ + "from dataclasses import dataclass, field, replace\n", + "from copy import deepcopy\n", + "\n", + "tree_at = lambda tree, inds: jax.tree.map(lambda x: x.at[inds].get(), tree)\n", + "\n", + "@dataclass\n", "class TestModule:\n", - " def __init__(self, node_attrs, edge_attrs, global_attrs):\n", - " self.node_attrs = node_attrs\n", - " self.edge_attrs = edge_attrs\n", - " self.global_attrs = global_attrs\n", - " self._nodes_in_view = jnp.arange(len(node_attrs[\"index\"]))\n", - " self._edges_in_view = jnp.arange(len(edge_attrs[\"index_pre\"]))\n", - " self.base = self\n", + "\n", + " node_attrs: dict[Any, Any]\n", + " edge_attrs: dict[Any, Any]\n", + " global_attrs: dict[Any, Any]\n", + "\n", + " base: TestModule = None\n", + "\n", + " def __post_init__(self):\n", + " if self.base is None:\n", + " self.base = self\n", + " \n", + " if \"externals\" not in self.global_attrs:\n", + " self.global_attrs[\"externals\"] = {}\n", + " if \"channels\" not in self.global_attrs:\n", + " self.global_attrs[\"channels\"] = {}\n", + " if \"synapses\" not in self.global_attrs:\n", + " self.global_attrs[\"synapses\"] = {}\n", + "\n", + " @property\n", + " def _nodes_in_view(self):\n", + " return self.node_attrs[(\"index\",)]\n", + " \n", + " @property\n", + " def _edges_in_view(self):\n", + " return self.edge_attrs[\"index_pre\"]\n", "\n", " @property\n", " def _num_nodes(self):\n", - " return len(self.node_attrs[\"index\"])\n", + " return len(self._nodes_in_view)\n", " \n", " @property\n", " def _num_edges(self):\n", - " return len(self.edge_attrs[\"index_pre\"])\n", + " return len(self._edges_in_view)\n", "\n", " def __repr__(self):\n", " node_keys = list(self.node_attrs.keys())\n", @@ -885,18 +255,20 @@ " global_keys = list(self.global_attrs.keys())\n", " return f\"TestModule(node_attrs={self._num_nodes}*{node_keys}, edge_attrs={self._num_edges}*{edge_keys}, global_attrs={global_keys})\"\n", "\n", - " def select_nodes(self, inds):\n", - " return jax.tree.map(lambda x: x.at[inds].get(), self.node_attrs)\n", + " def _select_nodes(self, inds):\n", + " return tree_at(self.node_attrs, inds)\n", "\n", - " def select_edges(self, inds):\n", - " return jax.tree.map(lambda x: x.at[inds].get(), self.edge_attrs)\n", + " def _select_edges(self, inds):\n", + " return tree_at(self.edge_attrs, inds)\n", "\n", " def select(self, nodes=None, edges=None):\n", - " self._nodes_in_view = self._nodes_in_view if nodes is None else nodes\n", - " self._edges_in_view = self._edges_in_view if edges is None else edges\n", - " view = TestModule(self.select_nodes(self._nodes_in_view), self.select_edges(self._edges_in_view), self.global_attrs)\n", - " view.base = self\n", - " return view\n", + " node_inds = self._nodes_in_view if nodes is None else nodes\n", + " edge_inds = self._edges_in_view if edges is None else edges\n", + "\n", + " node_attrs = self._select_nodes(node_inds)\n", + " edge_attrs = self._select_edges(edge_inds)\n", + "\n", + " return replace(self, node_attrs=node_attrs, edge_attrs=edge_attrs, base=self.base)\n", " \n", " @property\n", " def pandas(self):\n", @@ -914,35 +286,83 @@ " def globals(self):\n", " return self.pandas[2]\n", " \n", + " @property\n", + " def recordings(self):\n", + " df = pd.DataFrame.from_dict(self.globals[\"recordings\"], orient=\"index\").T.set_index(\"index\")\n", + " df.index.name = None\n", + " return df\n", + " \n", + " @property\n", + " def externals(self):\n", + " df = pd.DataFrame.from_dict(self.globals[\"externals\"], orient=\"index\").T.set_index(\"index\")\n", + " df.index.name = None\n", + " return df\n", + " \n", " def set(self, key, value):\n", - " if key in self.node_attrs:\n", - " self.base.node_attrs[key] = self.base.node_attrs[key].at[self._nodes_in_view].set(value)\n", + " if (\"morphology\", key) in self.node_attrs or (\"channels\", key):\n", + " node_attrs = self.base.node_attrs.copy()\n", + " node_attrs[(\"morphology\", key)] = node_attrs[(\"morphology\", key)].at[self._nodes_in_view].set(value)\n", + " updated_base = replace(self.base, node_attrs=node_attrs)\n", + " return replace(self, base=updated_base)\n", + " \n", " elif key in self.edge_attrs:\n", - " self.base.edge_attrs[key] = self.base.edge_attrs[key].at[self._edges_in_view].set(value)\n", + " edge_attrs = self.base.edge_attrs.copy()\n", + " edge_attrs[key] = edge_attrs[key].at[self._edges_in_view].set(value)\n", + " updated_base = replace(self.base, edge_attrs=edge_attrs)\n", + " return replace(self, base=updated_base)\n", + " \n", " elif key in self.global_attrs:\n", - " self.base.global_attrs[key] = self.base.global_attrs[key].at[:].set(value)\n", + " global_attrs = self.base.global_attrs.copy()\n", + " global_attrs[key] = global_attrs[key].at[:].set(value)\n", + " updated_base = replace(self.base, global_attrs=global_attrs)\n", + " return replace(self, base=updated_base)\n", + " \n", " else:\n", " raise ValueError(f\"Key {key} not found in any attribute\")\n", - " return TestModule(self.node_attrs, self.edge_attrs, self.global_attrs)\n", " \n", " def insert(self, channel):\n", - " self.base.global_attrs[\"channels\"][channel.name] = channel\n", + " global_attrs = self.base.global_attrs.copy()\n", + " global_attrs[\"channels\"][channel.name] = channel\n", + "\n", + " node_attrs = self.base.node_attrs.copy()\n", " for k, v in {**channel.states, **channel.params}.items():\n", - " self.base.node_attrs[k] = jnp.nan*jnp.stack([v]*self._num_nodes, axis=0)\n", - " self.base.node_attrs[k] = self.base.node_attrs[k].at[self._nodes_in_view].set(v)\n", - " return self.base\n", + " if (\"channels\", k) not in node_attrs:\n", + " node_attrs[(\"channels\", k)] = jnp.stack([jnp.nan*v]*self.base._num_nodes, axis=0)\n", + " node_attrs[(\"channels\", k)] = node_attrs[(\"channels\", k)].at[self._nodes_in_view].set(v)\n", + " \n", + " updated_base = replace(self.base, node_attrs=node_attrs, global_attrs=global_attrs)\n", + " return replace(self, base=updated_base)\n", " \n", - "def connect(pre_view, post_view, synapse):\n", - " pre_view.base.global_attrs[\"synapses\"][synapse.name] = synapse\n", - " for k, v in {**synapse.states, **synapse.params}.items():\n", - " pre_view.base.edge_attrs[k] = jnp.nan*jnp.stack([v]*pre_view._num_edges, axis=0)\n", - " pre_view.base.edge_attrs[k] = pre_view.base.edge_attrs[k].at[pre_view._edges_in_view].set(v)\n", - " return pre_view.base" + " # def record(self, key):\n", + " # if (\"recordings\", key) not in self.base.node_attrs:\n", + " # self.base.node_attrs[(\"recordings\", key)] = jnp.stack([False]*self.base._num_nodes, axis=0)\n", + " # self.base.node_attrs[(\"recordings\", key)] = self.base.node_attrs[(\"recordings\", key)].at[self._nodes_in_view].set(True)\n", + "\n", + " # def stimulate(self, key, values):\n", + " # if (\"externals\", key) not in self.base.node_attrs:\n", + " # self.base.node_attrs[(\"externals\", key)] = jnp.stack([False]*self.base._num_nodes, axis=0)\n", + " # self.base.node_attrs[(\"externals\", key)] = self.base.node_attrs[(\"externals\", key)].at[self._nodes_in_view].set(True)\n", + "\n", + " # for idx in self._nodes_in_view:\n", + " # self.base.global_attrs[\"externals\"][int(idx)] = values\n", + "\n", + " # def add_to_group(self, group):\n", + " # if (\"groups\", group) not in self.base.node_attrs:\n", + " # self.base.node_attrs[(\"groups\", group)] = jnp.stack([False]*self.base._num_nodes, axis=0)\n", + " # self.base.node_attrs[(\"groups\", group)] = self.base.node_attrs[(\"groups\", group)].at[self._nodes_in_view].set(True)\n", + " # return self\n", + " \n", + "# def connect(pre_view, post_view, synapse):\n", + "# pre_view.base.global_attrs[\"synapses\"][synapse.name] = synapse\n", + "# for k, v in {**synapse.states, **synapse.params}.items():\n", + "# pre_view.base.edge_attrs[k] = jnp.nan*jnp.stack([v]*pre_view._num_edges, axis=0)\n", + "# pre_view.base.edge_attrs[k] = pre_view.base.edge_attrs[k].at[pre_view._edges_in_view].set(v)\n", + "# return pre_view.base" ] }, { "cell_type": "code", - "execution_count": 822, + "execution_count": 95, "metadata": {}, "outputs": [], "source": [ @@ -961,187 +381,60 @@ }, { "cell_type": "code", - "execution_count": 823, + "execution_count": 96, "metadata": {}, "outputs": [], "source": [ "G = swc_to_nx(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", "jax_node_attrs, jax_edge_attrs, jax_global_attrs = nx_to_jax(G)\n", + "\n", + "jax_node_attrs = {(\"morphology\", k) if k != \"index\" else (k,): v for k, v in jax_node_attrs.items()}\n", + "\n", "cell = TestModule(jax_node_attrs, jax_edge_attrs, jax_global_attrs)\n", - "cell.global_attrs[\"channels\"] = {}\n", - "cell.global_attrs[\"synapses\"] = {}" + "view = cell.select(nodes=jnp.array([1, 2]))\n", + "view = view.insert(TestChannel())" ] }, { "cell_type": "code", - "execution_count": 825, + "execution_count": 99, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "TestModule(node_attrs=2630*['id', 'r', 'x', 'y', 'z', 'index', 'm', 'h', 'E', 'g'], edge_attrs=2629*['index_pre', 'index_post', 'g', 'E'], global_attrs=['channels', 'synapses'])" - ] - }, - "execution_count": 825, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "view = cell.select(nodes=jnp.array([1, 2]))\n", - "view.set(\"r\", 20)\n", - "cell.insert(TestChannel())\n", + "@jax.jit\n", + "def test():\n", + " new_cell = cell.select(nodes=jnp.array([1, 2])).set(\"r\", 20)\n", + "\n", + "test()\n", "\n", - "connect(cell.select(nodes=jnp.array([1, 2])), cell.select(nodes=jnp.array([3, 4])), TestSynapse())" + "# connect(cell.select(nodes=jnp.array([1, 2])), cell.select(nodes=jnp.array([3, 4])), TestSynapse())\n", + "\n", + "# cell.select(nodes=jnp.array([1, 2, 3, 4, 5])).select(nodes=jnp.array([1, 3])).insert(TestChannel()) # this is slow!\n", + "# cell.select(nodes=jnp.array([2, 3, 4, 5])).record(\"v\")\n", + "# cell.select(nodes=jnp.array([2, 3, 4, 5])).stimulate(\"i\", jnp.array([0.0, 0.0, 0.0, 0.0]))\n", + "# cell.select(nodes=jnp.array([2, 3, 4, 5])).add_to_group(\"test\")\n" ] }, { "cell_type": "code", - "execution_count": 827, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
gE
12[0.0][0.0]
852[0.0][0.0]
1412[0.0][0.0]
23[0.0][0.0]
34[0.0][0.0]
............
26252626[0.0][0.0]
26262627[0.0][0.0]
26272628[0.0][0.0]
26282629[0.0][0.0]
26292630[0.0][0.0]
\n", - "

2629 rows × 2 columns

\n", - "
" - ], - "text/plain": [ - " g E\n", - "1 2 [0.0] [0.0]\n", - " 852 [0.0] [0.0]\n", - " 1412 [0.0] [0.0]\n", - "2 3 [0.0] [0.0]\n", - "3 4 [0.0] [0.0]\n", - "... ... ...\n", - "2625 2626 [0.0] [0.0]\n", - "2626 2627 [0.0] [0.0]\n", - "2627 2628 [0.0] [0.0]\n", - "2628 2629 [0.0] [0.0]\n", - "2629 2630 [0.0] [0.0]\n", - "\n", - "[2629 rows x 2 columns]" - ] - }, - "execution_count": 827, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cell.edges" - ] + "outputs": [], + "source": [] }, { "cell_type": "code", - "execution_count": 536, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "TestModule(node_attrs=3*['id', 'index', 'r', 'x', 'y', 'z'], edge_attrs=2*['index'], global_attrs=[])" - ] - }, - "execution_count": 536, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cell.select(nodes=jnp.array([0, 1, 2]))" - ] + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] }, { "cell_type": "code", From aaae537eb4e6daeb503cb48316ed10199ea7e442 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Wed, 16 Jul 2025 17:51:26 +0200 Subject: [PATCH 23/24] wip: experimenting with basic concepts --- dev.ipynb | 571 +++++++++++++++++++++++++++++------------------------- 1 file changed, 310 insertions(+), 261 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index bd174028c..13c713e2e 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -204,14 +204,51 @@ }, { "cell_type": "code", - "execution_count": 94, + "execution_count": 479, "metadata": {}, "outputs": [], "source": [ - "from dataclasses import dataclass, field, replace\n", - "from copy import deepcopy\n", + "def tree_filter(tree, condition, do_x = None, do_y = None):\n", + " do_x = lambda x: None if do_x is None else do_x\n", + " do_y = lambda x: None if do_y is None else do_y\n", "\n", - "tree_at = lambda tree, inds: jax.tree.map(lambda x: x.at[inds].get(), tree)\n", + " update_if = lambda path, val: do_x(val) if condition(path, val) else do_y(val)\n", + " return jax.tree_util.tree_map_with_path(update_if, tree)\n", + "\n", + "def tree_apply_at(tree, func_mapper: Union[dict[str, callable], callable]):\n", + " if isinstance(func_mapper, Callable):\n", + " return jax.tree.map(lambda x: func_mapper(x), tree)\n", + " \n", + " def update_if_key_matches(path, value):\n", + " if (key := path[0].key) in func_mapper:\n", + " return func_mapper[key](value)\n", + " return value\n", + " return jax.tree_util.tree_map_with_path(update_if_key_matches, tree)\n", + "\n", + "def tree_set_at(tree, keys_values: Union[dict[str, Any], Any], inds = None):\n", + " inds = slice(None) if inds is None else inds\n", + " setter = lambda v: lambda x: x.at[inds].set(v)\n", + " if not isinstance(keys_values, dict):\n", + " return tree_apply_at(tree, setter(keys_values))\n", + " return tree_apply_at(tree, {k: setter(v) for k, v in keys_values.items()})\n", + "\n", + "def tree_get_at(tree, keys = None, inds = None):\n", + " inds = slice(None) if inds is None else inds\n", + " getter = lambda x: x.at[inds].get()\n", + " if keys is None:\n", + " return tree_apply_at(tree, getter)\n", + " return tree_apply_at(tree, {k: getter for k in keys})\n", + "\n", + "has_top_level_key = lambda d, key: any(k[0] == key for k in d)" + ] + }, + { + "cell_type": "code", + "execution_count": 501, + "metadata": {}, + "outputs": [], + "source": [ + "from dataclasses import dataclass, field, replace\n", "\n", "@dataclass\n", "class TestModule:\n", @@ -255,21 +292,42 @@ " global_keys = list(self.global_attrs.keys())\n", " return f\"TestModule(node_attrs={self._num_nodes}*{node_keys}, edge_attrs={self._num_edges}*{edge_keys}, global_attrs={global_keys})\"\n", "\n", - " def _select_nodes(self, inds):\n", - " return tree_at(self.node_attrs, inds)\n", + " def _select_nodes(self, keys = None, inds = None):\n", + " return tree_get_at(self.node_attrs, keys=keys, inds=inds)\n", "\n", - " def _select_edges(self, inds):\n", - " return tree_at(self.edge_attrs, inds)\n", + " def _select_edges(self, keys = None, inds = None):\n", + " return tree_get_at(self.edge_attrs, keys=keys, inds=inds)\n", + " \n", + " def _set_node_attrs(self, keys_values, inds = None):\n", + " inds = self._nodes_in_view if inds is None else inds\n", + " node_attrs = tree_set_at(self.base.node_attrs, keys_values=keys_values, inds=inds)\n", + " updated_base = replace(self.base, node_attrs=node_attrs)\n", + " updated_node_attrs = updated_base._select_nodes(inds=inds)\n", + " updated_view = replace(self, base=updated_base, node_attrs=updated_node_attrs)\n", + " return updated_view\n", + " \n", + " def _set_edge_attrs(self, keys_values, inds = None):\n", + " return tree_set_at(self.edge_attrs, keys_values=keys_values, inds=inds)\n", "\n", " def select(self, nodes=None, edges=None):\n", " node_inds = self._nodes_in_view if nodes is None else nodes\n", " edge_inds = self._edges_in_view if edges is None else edges\n", "\n", - " node_attrs = self._select_nodes(node_inds)\n", - " edge_attrs = self._select_edges(edge_inds)\n", + " node_attrs = self._select_nodes(inds=node_inds)\n", + " edge_attrs = self._select_edges(inds=edge_inds)\n", "\n", " return replace(self, node_attrs=node_attrs, edge_attrs=edge_attrs, base=self.base)\n", " \n", + " def _init_node_attrs(self, d: dict[str, Any], inds = None, init_value = jnp.nan):\n", + " inds = self._nodes_in_view if inds is None else inds\n", + " data_type = lambda x: x.dtype if isinstance(x, jnp.ndarray) else np.dtype(type(x))\n", + " init_node_attrs = jax.tree.map(lambda x: jnp.stack([init_value*x]*self._num_nodes, axis=0, dtype=data_type(x)), d)\n", + " base_node_attrs = self.base.node_attrs.copy()\n", + " base_node_attrs.update(init_node_attrs)\n", + " updated_base = replace(self.base, node_attrs=base_node_attrs)\n", + " init_view = replace(self, base=updated_base)\n", + " return init_view._set_node_attrs(keys_values=d, inds=inds)\n", + " \n", " @property\n", " def pandas(self):\n", " return jax_to_pandas(self.node_attrs, self.edge_attrs, self.global_attrs)\n", @@ -299,70 +357,85 @@ " return df\n", " \n", " def set(self, key, value):\n", - " if (\"morphology\", key) in self.node_attrs or (\"channels\", key):\n", - " node_attrs = self.base.node_attrs.copy()\n", - " node_attrs[(\"morphology\", key)] = node_attrs[(\"morphology\", key)].at[self._nodes_in_view].set(value)\n", - " updated_base = replace(self.base, node_attrs=node_attrs)\n", - " return replace(self, base=updated_base)\n", - " \n", - " elif key in self.edge_attrs:\n", - " edge_attrs = self.base.edge_attrs.copy()\n", - " edge_attrs[key] = edge_attrs[key].at[self._edges_in_view].set(value)\n", - " updated_base = replace(self.base, edge_attrs=edge_attrs)\n", - " return replace(self, base=updated_base)\n", + " is_morph_key = (\"morphology\", key) in self.node_attrs\n", + " is_channel_key = (\"channels\", key) in self.node_attrs\n", + "\n", + " if is_morph_key or is_channel_key:\n", + " key = (\"morphology\", key) if is_morph_key else (\"channels\", key)\n", + " updated_view = self._set_node_attrs(keys_values={key: value}, inds=self._nodes_in_view)\n", + " return updated_view\n", " \n", - " elif key in self.global_attrs:\n", - " global_attrs = self.base.global_attrs.copy()\n", - " global_attrs[key] = global_attrs[key].at[:].set(value)\n", - " updated_base = replace(self.base, global_attrs=global_attrs)\n", - " return replace(self, base=updated_base)\n", + " # elif key in self.edge_attrs:\n", + " # updated_base = self.base._set_edges([key], [value], self._edges_in_view)\n", + " \n", + " # updated_edge_attrs = updated_base._select_edges(inds=self._edges_in_view)\n", + " # updated_view = replace(self, base=updated_base, edge_attrs=updated_edge_attrs)\n", + " # return updated_view\n", " \n", " else:\n", - " raise ValueError(f\"Key {key} not found in any attribute\")\n", + " raise ValueError(f\"Key {key} not found or not mutable via `.set()`\")\n", " \n", " def insert(self, channel):\n", - " global_attrs = self.base.global_attrs.copy()\n", - " global_attrs[\"channels\"][channel.name] = channel\n", - "\n", - " node_attrs = self.base.node_attrs.copy()\n", - " for k, v in {**channel.states, **channel.params}.items():\n", - " if (\"channels\", k) not in node_attrs:\n", - " node_attrs[(\"channels\", k)] = jnp.stack([jnp.nan*v]*self.base._num_nodes, axis=0)\n", - " node_attrs[(\"channels\", k)] = node_attrs[(\"channels\", k)].at[self._nodes_in_view].set(v)\n", - " \n", - " updated_base = replace(self.base, node_attrs=node_attrs, global_attrs=global_attrs)\n", - " return replace(self, base=updated_base)\n", - " \n", - " # def record(self, key):\n", - " # if (\"recordings\", key) not in self.base.node_attrs:\n", - " # self.base.node_attrs[(\"recordings\", key)] = jnp.stack([False]*self.base._num_nodes, axis=0)\n", - " # self.base.node_attrs[(\"recordings\", key)] = self.base.node_attrs[(\"recordings\", key)].at[self._nodes_in_view].set(True)\n", - "\n", - " # def stimulate(self, key, values):\n", - " # if (\"externals\", key) not in self.base.node_attrs:\n", - " # self.base.node_attrs[(\"externals\", key)] = jnp.stack([False]*self.base._num_nodes, axis=0)\n", - " # self.base.node_attrs[(\"externals\", key)] = self.base.node_attrs[(\"externals\", key)].at[self._nodes_in_view].set(True)\n", - "\n", - " # for idx in self._nodes_in_view:\n", - " # self.base.global_attrs[\"externals\"][int(idx)] = values\n", - "\n", - " # def add_to_group(self, group):\n", - " # if (\"groups\", group) not in self.base.node_attrs:\n", - " # self.base.node_attrs[(\"groups\", group)] = jnp.stack([False]*self.base._num_nodes, axis=0)\n", - " # self.base.node_attrs[(\"groups\", group)] = self.base.node_attrs[(\"groups\", group)].at[self._nodes_in_view].set(True)\n", - " # return self\n", + " base_global_attrs = self.base.global_attrs.copy()\n", + " channel_param_states = {**channel.states, **channel.params, channel.name: True}\n", + " channel_setter = {(\"channels\", k): v for k,v in channel_param_states.items()}\n", + " if not channel.name in base_global_attrs[\"channels\"]:\n", + " base_global_attrs[\"channels\"][channel.name] = channel\n", + " updated_base = replace(self.base, global_attrs=base_global_attrs)\n", + " updated_view = replace(self, base=updated_base)\n", + " updated_view = updated_view._init_node_attrs(channel_setter)\n", + " return updated_view\n", + " else:\n", + " return self._set_node_attrs(keys_values=channel_setter)\n", + "\n", " \n", + " def record(self, key):\n", + " if (\"recordings\", key) not in self.base.node_attrs:\n", + " return self._init_node_attrs({(\"recordings\", key): True}, init_value=False)\n", + " else:\n", + " return self._set_node_attrs({(\"recordings\", key): True})\n", + "\n", + " def add_to_group(self, group):\n", + " if (\"groups\", group) not in self.base.node_attrs:\n", + " return self._init_node_attrs({(\"groups\", group): True}, init_value=False)\n", + " else:\n", + " return self._set_node_attrs({(\"groups\", group): True})\n", + "\n", + " def stimulate(self, key, values):\n", + " \n", + " if (\"externals\", key) not in self.base.node_attrs:\n", + " updated_view = self._init_node_attrs({(\"externals\", key): True}, init_value=False)\n", + " else:\n", + " updated_view = self._set_node_attrs({(\"externals\", key): True})\n", + " \n", + " for idx in self._nodes_in_view:\n", + " updated_view.base.global_attrs[\"externals\"][(key, int(idx))] = values\n", + " updated_view.global_attrs[\"externals\"][(key, int(idx))] = values\n", + "\n", + " return updated_view\n", + "\n", + "\n", "# def connect(pre_view, post_view, synapse):\n", - "# pre_view.base.global_attrs[\"synapses\"][synapse.name] = synapse\n", + "# pre_view_base_global_attrs = pre_view.base.global_attrs.copy()\n", + "# pre_view_base_global_attrs[\"synapses\"][synapse.name] = synapse\n", + " \n", + "# pre_view_base_edge_attrs = pre_view.base.edge_attrs.copy()\n", + "# pre_nodes = pre_view._nodes_in_view\n", + "# post_nodes = post_view._nodes_in_view\n", + "\n", "# for k, v in {**synapse.states, **synapse.params}.items():\n", - "# pre_view.base.edge_attrs[k] = jnp.nan*jnp.stack([v]*pre_view._num_edges, axis=0)\n", - "# pre_view.base.edge_attrs[k] = pre_view.base.edge_attrs[k].at[pre_view._edges_in_view].set(v)\n", - "# return pre_view.base" + "# pre_view_base_edge_attrs[k] = jnp.nan*jnp.stack([v]*pre_view._num_edges, axis=0)\n", + "# pre_view_base_edge_attrs[k] = pre_view_base_edge_attrs[k].at[pre_view._edges_in_view].set(v)\n", + "\n", + "# updated_base = replace(pre_view.base, edge_attrs=pre_view_base_edge_attrs, global_attrs=pre_view_base_global_attrs)\n", + "# updated_edge_attrs = updated_base._select_edges(pre_view._edges_in_view)\n", + "\n", + "# return " ] }, { "cell_type": "code", - "execution_count": 95, + "execution_count": 502, "metadata": {}, "outputs": [], "source": [ @@ -370,34 +443,203 @@ " def __init__(self, name=None):\n", " self.name = name if name is not None else \"TestChannel\"\n", " self.states = {\"m\": 0.0, \"h\": 0.0}\n", - " self.params = {\"E\": jnp.array([0.0]), \"g\": jnp.array([[0.0, 0.0], [0.0, 0.0]])}\n", + " # self.params = {\"E\": jnp.array([0.0]), \"g\": jnp.array([[0.0, 0.0], [0.0, 0.0]])}\n", + " self.params = {\"E\": 0.0, \"g\": 0.0}\n", "\n", "class TestSynapse:\n", " def __init__(self, name=None):\n", " self.name = name if name is not None else \"TestSynapse\"\n", " self.states = {\"g\": 0.0}\n", - " self.params = {\"E\": jnp.array([0.0]), \"g\": jnp.array([0.0])}" + " # self.params = {\"E\": jnp.array([0.0]), \"g\": jnp.array([0.0])}\n", + " self.params = {\"E\": 0.0, \"g\": 0.0}" ] }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 503, "metadata": {}, "outputs": [], "source": [ "G = swc_to_nx(\"../jaxley/tests/swc_files/morph_ca1_n120.swc\")\n", "jax_node_attrs, jax_edge_attrs, jax_global_attrs = nx_to_jax(G)\n", + "jax_node_attrs[\"index\"] = jax_node_attrs[\"index\"] -1 # TMP FIX FOR INDEXING, otherwise index drift for select\n", "\n", "jax_node_attrs = {(\"morphology\", k) if k != \"index\" else (k,): v for k, v in jax_node_attrs.items()}\n", "\n", "cell = TestModule(jax_node_attrs, jax_edge_attrs, jax_global_attrs)\n", - "view = cell.select(nodes=jnp.array([1, 2]))\n", - "view = view.insert(TestChannel())" + "view = cell.select(nodes=jnp.array([1, 2, 4, 6, 7]))\n", + "\n", + "view = view.set(\"r\", 20)\n", + "view = view.insert(TestChannel())\n", + "view = view.record(\"i\")\n", + "view = view.add_to_group(\"test\")\n", + "view = view.stimulate(\"i\", jnp.array([0.0, 0.0]))" + ] + }, + { + "cell_type": "code", + "execution_count": 504, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
channelsexternalsgroupsmorphologyrecordings
ETestChannelghmitestidrxyzi
10.0True0.00.00.0TrueTrue120.01.85-4.030.0True
20.0True0.00.00.0TrueTrue120.01.98-6.000.0True
40.0True0.00.00.0TrueTrue120.02.17-8.490.0True
60.0True0.00.00.0TrueTrue120.02.74-9.850.0True
70.0True0.00.00.0TrueTrue120.03.00-10.350.0True
\n", + "
" + ], + "text/plain": [ + " channels externals groups morphology \\\n", + " E TestChannel g h m i test id r x \n", + "1 0.0 True 0.0 0.0 0.0 True True 1 20.0 1.85 \n", + "2 0.0 True 0.0 0.0 0.0 True True 1 20.0 1.98 \n", + "4 0.0 True 0.0 0.0 0.0 True True 1 20.0 2.17 \n", + "6 0.0 True 0.0 0.0 0.0 True True 1 20.0 2.74 \n", + "7 0.0 True 0.0 0.0 0.0 True True 1 20.0 3.00 \n", + "\n", + " recordings \n", + " y z i \n", + "1 -4.03 0.0 True \n", + "2 -6.00 0.0 True \n", + "4 -8.49 0.0 True \n", + "6 -9.85 0.0 True \n", + "7 -10.35 0.0 True " + ] + }, + "execution_count": 504, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "view.nodes" ] }, { "cell_type": "code", - "execution_count": 99, + "execution_count": 467, "metadata": {}, "outputs": [], "source": [ @@ -414,199 +656,6 @@ "# cell.select(nodes=jnp.array([2, 3, 4, 5])).stimulate(\"i\", jnp.array([0.0, 0.0, 0.0, 0.0]))\n", "# cell.select(nodes=jnp.array([2, 3, 4, 5])).add_to_group(\"test\")\n" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 867, - "metadata": {}, - "outputs": [], - "source": [ - "@jax.tree_util.register_dataclass\n", - "@dataclass\n", - "class MorphTree:\n", - " \"\"\"MorphTree is a custom cataclass that holds the node and edge attributes of a morphology.\n", - " \n", - " MorphTree is used to store the node and edge attributes of a morphology / jaxley Module\n", - " as a pytree, to allow for easy manipulation of the Module / morphology parameters \n", - " using jax transformations.\n", - "\n", - " MorphTree also allows for easy conversion to and from pandas DataFrames, and networkx \n", - " DiGraphs, as well as basic convenience functions for plotting and renaming or reordering\n", - " of nodes and edges.\n", - " \"\"\"\n", - " node_attrs: Dict[int, Dict[str, Any]]\n", - " edge_attrs: Dict[Tuple[int, int], Dict[str, Any]]\n", - " global_attrs: Dict[str, Any] = field(default_factory=dict)\n", - "\n", - " @property\n", - " def nodes(self) -> jnp.ndarray:\n", - " \"\"\"Returns the node indices as a jax array.\"\"\"\n", - " return jnp.array(list(self.node_attrs.keys())).astype(int)\n", - "\n", - " @property\n", - " def edges(self) -> jnp.ndarray:\n", - " \"\"\"Returns the edge indices as a jax array.\"\"\"\n", - " return jnp.array(list(self.edge_attrs.keys())).astype(int)\n", - "\n", - " def __repr__(self) -> str:\n", - " n_nodes = len(self.node_attrs)\n", - " n_edges = len(self.edge_attrs)\n", - "\n", - " node_keys = list(next(iter(self.node_attrs.values())).keys())\n", - " if len(self.edge_attrs) > 0:\n", - " edge_keys = list(next(iter(self.edge_attrs.values())).keys())\n", - " else:\n", - " edge_keys = []\n", - "\n", - " node_attrs = node_keys if len(self.node_attrs) > 0 else []\n", - " edge_attrs = edge_keys if len(self.edge_attrs) > 0 else []\n", - " return f\"MorphTree(nodes={n_nodes}*{node_attrs}, edges={n_edges}*{edge_attrs}, global={list(self.global_attrs.keys())})\"\n", - " \n", - " def __iter__(self):\n", - " \"\"\"Allows unpacking of MorphTree as: node_attrs, edge_attrs, global_attrs = *tree\"\"\"\n", - " yield self.node_attrs\n", - " yield self.edge_attrs\n", - " yield self.global_attrs\n", - " \n", - " def node(self, i: int) -> Dict[str, Any]:\n", - " \"\"\"Returns the node attributes for the node with index i.\"\"\"\n", - " return self.node_attrs[i]\n", - " \n", - " def edge(self, i: int, j: int) -> Dict[str, Any]:\n", - " \"\"\"Returns the edge attributes for the edge between nodes i and j.\"\"\"\n", - " return self.edge_attrs[i, j]\n", - " \n", - " def to_nx(self) -> nx.DiGraph:\n", - " \"\"\"Returns the MorphTree as a networkx DiGraph.\"\"\"\n", - " G = nx.DiGraph()\n", - " G.add_nodes_from(self.node_attrs.items())\n", - " G.add_edges_from((i, j, d) for (i, j), d in self.edge_attrs.items())\n", - " G.graph.update(self.global_attrs)\n", - " return G\n", - " \n", - " @staticmethod\n", - " def from_nx(G: nx.DiGraph) -> MorphTree:\n", - " \"\"\"Returns a MorphTree from a networkx DiGraph.\"\"\"\n", - " node_attrs = {n: G.nodes[n] for n in G.nodes}\n", - " edge_attrs = {(i, j): G.edges[i, j] for i, j in G.edges}\n", - " return MorphTree(node_attrs, edge_attrs, G.graph)\n", - " \n", - " def to_pandas(self, return_global_attrs: bool = True) -> Tuple[pd.DataFrame, pd.DataFrame]:\n", - " \"\"\"Returns the MorphTree as a pandas DataFrame.\"\"\"\n", - " node_df = pd.DataFrame(self.node_attrs.values(), index=self.node_attrs.keys())\n", - " edge_df = pd.DataFrame(self.edge_attrs.values(), index=self.edge_attrs.keys())\n", - " edge_index = pd.MultiIndex.from_arrays(np.array(self.edges).T)\n", - " edge_df = edge_df.set_index(edge_index)\n", - "\n", - " if return_global_attrs:\n", - " return node_df, edge_df, pd.Series(self.global_attrs)\n", - " return node_df, edge_df\n", - " \n", - " @staticmethod\n", - " def from_pandas(node_df: pd.DataFrame, edge_df: pd.DataFrame, global_attrs: pd.Series = pd.Series()) -> MorphTree:\n", - " \"\"\"Returns a MorphTree from a pandas DataFrame.\"\"\"\n", - " node_attrs = node_df.to_dict(orient=\"index\")\n", - " edge_attrs = edge_df.to_dict(orient=\"index\")\n", - " return MorphTree(node_attrs, edge_attrs, global_attrs.to_dict())\n", - " \n", - " def plot(self, dims=(0,1), ax: Optional[Axes] = None, **kwargs: Any) -> Axes:\n", - " \"\"\"Uses networkx to plot the MorphTree.\n", - " \n", - " Args:\n", - " dims: Dimensions to plot (0:x, 1:y, 2:z).\n", - " ax: plt.Axes.\n", - " **kwargs: kwargs for networkx.draw.\n", - "\n", - " Returns:\n", - " The Axes object on which the MorphTree was plotted.\n", - " \"\"\"\n", - " G = self.to_nx()\n", - " pos = {}\n", - " dims2axes = {0: \"x\", 1: \"y\", 2: \"z\"}\n", - " for n, attr in G.nodes(data=True):\n", - " if \"x\" in attr: # assume y is also present\n", - " pos[n] = (attr[dims2axes[dims[0]]], attr[dims2axes[dims[1]]])\n", - " \n", - " ax = ax if ax is not None else plt.gca()\n", - " nx.draw(G, pos, with_labels=True, ax=ax, **kwargs)\n", - " return ax\n", - "\n", - " def reindex_nodes(self, mapping: dict) -> MorphTree:\n", - " \"\"\"Reindexes the nodes of the MorphTree according to the mapping dictionary.\n", - " \n", - " Args:\n", - " mapping: A dict mapping the old to new node indices.\n", - "\n", - " Returns:\n", - " A new MorphTree with the nodes reindexed according to the mapping.\n", - " \"\"\"\n", - " new_node_attrs = {mapping[i]: attrs for i, attrs in self.node_attrs.items()}\n", - " \n", - " new_edge_attrs = {}\n", - " for (i, j), attrs in self.edge_attrs.items():\n", - " new_edge_attrs[(mapping[i], mapping[j])] = attrs\n", - " \n", - " return MorphTree(new_node_attrs, new_edge_attrs, self.global_attrs)\n", - " \n", - " def reorder_tree(self, new_order: jnp.ndarray) -> MorphTree:\n", - " \"\"\"Reorders the nodes of the MorphTree according to the new order.\n", - " \n", - " Edges are flipped to ensure they are always in ascending order.\n", - " \n", - " Args:\n", - " new_order: New node order. new_order[i] is the new index of node i.\n", - "\n", - " Returns:\n", - " A new MorphTree with the nodes reordered according to the new order.\n", - " \"\"\"\n", - " # TODO: check this does what I think it does, i.e. change the edge orientation\n", - " # in order of appearance of the nodes in self.nodes.\n", - " edges = np.array(self.edges)\n", - " np_order = np.array(new_order)\n", - " idx_i = np.where(edges[:,0] == np_order[:, None])[0]\n", - " idx_j = np.where(edges[:,1] == np_order[:, None])[0]\n", - " is_descending = ~(idx_i < idx_j)\n", - " for (i,j) in edges[is_descending]:\n", - " print(i,j)\n", - " self.edge_attrs[j, i] = self.edge_attrs.pop((i, j))\n", - " return self\n", - " \n", - " def subgraph(self, nodes: List[int]) -> MorphTree:\n", - " \"\"\"Returns a subset of nodes in the MorphTree.\n", - "\n", - " Edges are only included if both nodes are in the subgraph.\n", - " \n", - " Args:\n", - " nodes: List of node indices to include in the subgraph.\n", - "\n", - " Returns:\n", - " A new MorphTree containing only the specified nodes and their edges.\n", - " \"\"\"\n", - " node_attrs_subset = {i: self.node_attrs[i] for i in nodes}\n", - " edge_attrs_subset = {(i,j): attrs for (i,j), attrs in self.edge_attrs.items() if i in nodes and j in nodes}\n", - " return MorphTree(node_attrs_subset, edge_attrs_subset, self.global_attrs)\n" - ] } ], "metadata": { From 06967ffefd10386103f26e5983857bed84c2d063 Mon Sep 17 00:00:00 2001 From: jnsbck-uni Date: Thu, 17 Jul 2025 14:22:05 +0200 Subject: [PATCH 24/24] wip: more experiments [skip ci] --- dev.ipynb | 361 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 266 insertions(+), 95 deletions(-) diff --git a/dev.ipynb b/dev.ipynb index 13c713e2e..409104d71 100644 --- a/dev.ipynb +++ b/dev.ipynb @@ -47,7 +47,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 549, "metadata": {}, "outputs": [], "source": [ @@ -172,8 +172,10 @@ " node_index = np.array(jax_node_attrs[(\"index\",)])\n", " node_attrs_df = pd.DataFrame({k:v.tolist() for k, v in jax_node_attrs.items()}, index=node_index).drop(columns=[(\"index\",)])\n", " \n", - " edge_index = pd.MultiIndex.from_arrays(np.vstack([jax_edge_attrs[\"index_pre\"], jax_edge_attrs[\"index_post\"]]))\n", - " edge_attrs_df = pd.DataFrame({k:v.tolist() for k, v in jax_edge_attrs.items()}, index = edge_index).drop(columns=[\"index_pre\", \"index_post\"])\n", + " # edge_index = pd.MultiIndex.from_arrays(np.vstack([jax_edge_attrs[\"index_pre\"], jax_edge_attrs[\"index_post\"]]))\n", + " # edge_attrs_df = pd.DataFrame({k:v.tolist() for k, v in jax_edge_attrs.items()}, index = edge_index).drop(columns=[\"index_pre\", \"index_post\"])\n", + " edge_index = np.array(jax_edge_attrs[\"index\"])\n", + " edge_attrs_df = pd.DataFrame({k:v.tolist() for k, v in jax_edge_attrs.items()}, index = edge_index).drop(columns=[\"index\"])\n", "\n", " global_attrs_df = pd.Series(jax_global_attrs)\n", "\n", @@ -193,9 +195,11 @@ " inds, jax_node_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *node_attrs.items())\n", " jax_node_attrs[(\"index\", )] = jnp.array(inds)\n", "\n", - " *inds, jax_edge_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *edge_attrs.items())\n", - " jax_edge_attrs[\"index_pre\"] = jnp.array(inds[0])\n", - " jax_edge_attrs[\"index_post\"] = jnp.array(inds[1])\n", + " # *inds, jax_edge_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *edge_attrs.items())\n", + " # jax_edge_attrs[\"index_pre\"] = jnp.array(inds[0])\n", + " # jax_edge_attrs[\"index_post\"] = jnp.array(inds[1])\n", + " inds, jax_edge_attrs = jax.tree_util.tree_map(lambda *args: jnp.array(args), *edge_attrs.items())\n", + " jax_edge_attrs[\"index\"] = jnp.array(inds)\n", "\n", " jax_global_attrs = {k: jnp.array(v) for k, v in global_attrs.items()}\n", "\n", @@ -204,10 +208,12 @@ }, { "cell_type": "code", - "execution_count": 479, + "execution_count": 683, "metadata": {}, "outputs": [], "source": [ + "from typing import Union, Any, Callable\n", + "\n", "def tree_filter(tree, condition, do_x = None, do_y = None):\n", " do_x = lambda x: None if do_x is None else do_x\n", " do_y = lambda x: None if do_y is None else do_y\n", @@ -239,12 +245,15 @@ " return tree_apply_at(tree, getter)\n", " return tree_apply_at(tree, {k: getter for k in keys})\n", "\n", + "def tree_concat(tree, other, axis=0):\n", + " return jax.tree.map(lambda x, y: jnp.concatenate([x, y], axis=axis), tree, other)\n", + "\n", "has_top_level_key = lambda d, key: any(k[0] == key for k in d)" ] }, { "cell_type": "code", - "execution_count": 501, + "execution_count": 618, "metadata": {}, "outputs": [], "source": [ @@ -276,7 +285,7 @@ " \n", " @property\n", " def _edges_in_view(self):\n", - " return self.edge_attrs[\"index_pre\"]\n", + " return self.edge_attrs[\"index\"]\n", "\n", " @property\n", " def _num_nodes(self):\n", @@ -307,7 +316,12 @@ " return updated_view\n", " \n", " def _set_edge_attrs(self, keys_values, inds = None):\n", - " return tree_set_at(self.edge_attrs, keys_values=keys_values, inds=inds)\n", + " inds = self._edges_in_view if inds is None else inds\n", + " edge_attrs = tree_set_at(self.base.edge_attrs, keys_values=keys_values, inds=inds)\n", + " updated_base = replace(self.base, edge_attrs=edge_attrs)\n", + " updated_edge_attrs = updated_base._select_edges(inds=inds)\n", + " updated_view = replace(self, base=updated_base, edge_attrs=updated_edge_attrs)\n", + " return updated_view\n", "\n", " def select(self, nodes=None, edges=None):\n", " node_inds = self._nodes_in_view if nodes is None else nodes\n", @@ -321,13 +335,23 @@ " def _init_node_attrs(self, d: dict[str, Any], inds = None, init_value = jnp.nan):\n", " inds = self._nodes_in_view if inds is None else inds\n", " data_type = lambda x: x.dtype if isinstance(x, jnp.ndarray) else np.dtype(type(x))\n", - " init_node_attrs = jax.tree.map(lambda x: jnp.stack([init_value*x]*self._num_nodes, axis=0, dtype=data_type(x)), d)\n", + " init_node_attrs = jax.tree.map(lambda x: jnp.stack([init_value*x]*self.base._num_nodes, axis=0, dtype=data_type(x)), d)\n", " base_node_attrs = self.base.node_attrs.copy()\n", " base_node_attrs.update(init_node_attrs)\n", " updated_base = replace(self.base, node_attrs=base_node_attrs)\n", " init_view = replace(self, base=updated_base)\n", " return init_view._set_node_attrs(keys_values=d, inds=inds)\n", " \n", + " def _init_edge_attrs(self, d: dict[str, Any], inds = None, init_value = jnp.nan):\n", + " inds = self._edges_in_view if inds is None else inds\n", + " data_type = lambda x: x.dtype if isinstance(x, jnp.ndarray) else np.dtype(type(x))\n", + " init_edge_attrs = jax.tree.map(lambda x: jnp.stack([init_value*x]*self.base._num_edges, axis=0, dtype=data_type(x)), d)\n", + " base_edge_attrs = self.base.edge_attrs.copy()\n", + " base_edge_attrs.update(init_edge_attrs)\n", + " updated_base = replace(self.base, edge_attrs=base_edge_attrs)\n", + " init_view = replace(self, base=updated_base)\n", + " return init_view._set_edge_attrs(keys_values=d, inds=inds)\n", + " \n", " @property\n", " def pandas(self):\n", " return jax_to_pandas(self.node_attrs, self.edge_attrs, self.global_attrs)\n", @@ -365,12 +389,12 @@ " updated_view = self._set_node_attrs(keys_values={key: value}, inds=self._nodes_in_view)\n", " return updated_view\n", " \n", - " # elif key in self.edge_attrs:\n", - " # updated_base = self.base._set_edges([key], [value], self._edges_in_view)\n", + " elif key in self.edge_attrs:\n", + " updated_base = self.base._set_edges([key], [value], self._edges_in_view)\n", " \n", - " # updated_edge_attrs = updated_base._select_edges(inds=self._edges_in_view)\n", - " # updated_view = replace(self, base=updated_base, edge_attrs=updated_edge_attrs)\n", - " # return updated_view\n", + " updated_edge_attrs = updated_base._select_edges(inds=self._edges_in_view)\n", + " updated_view = replace(self, base=updated_base, edge_attrs=updated_edge_attrs)\n", + " return updated_view\n", " \n", " else:\n", " raise ValueError(f\"Key {key} not found or not mutable via `.set()`\")\n", @@ -386,8 +410,7 @@ " updated_view = updated_view._init_node_attrs(channel_setter)\n", " return updated_view\n", " else:\n", - " return self._set_node_attrs(keys_values=channel_setter)\n", - "\n", + " return self._set_node_attrs(channel_setter)\n", " \n", " def record(self, key):\n", " if (\"recordings\", key) not in self.base.node_attrs:\n", @@ -415,27 +438,59 @@ " return updated_view\n", "\n", "\n", - "# def connect(pre_view, post_view, synapse):\n", - "# pre_view_base_global_attrs = pre_view.base.global_attrs.copy()\n", - "# pre_view_base_global_attrs[\"synapses\"][synapse.name] = synapse\n", + "def connect(pre_view, post_view, synapse):\n", + " base_global_attrs = pre_view.base.global_attrs.copy()\n", + " synapse_param_states = {**synapse.states, **synapse.params, synapse.name: True}\n", + " synapse_setter = {k: v for k,v in synapse_param_states.items()}\n", " \n", - "# pre_view_base_edge_attrs = pre_view.base.edge_attrs.copy()\n", - "# pre_nodes = pre_view._nodes_in_view\n", - "# post_nodes = post_view._nodes_in_view\n", - "\n", - "# for k, v in {**synapse.states, **synapse.params}.items():\n", - "# pre_view_base_edge_attrs[k] = jnp.nan*jnp.stack([v]*pre_view._num_edges, axis=0)\n", - "# pre_view_base_edge_attrs[k] = pre_view_base_edge_attrs[k].at[pre_view._edges_in_view].set(v)\n", - "\n", - "# updated_base = replace(pre_view.base, edge_attrs=pre_view_base_edge_attrs, global_attrs=pre_view_base_global_attrs)\n", - "# updated_edge_attrs = updated_base._select_edges(pre_view._edges_in_view)\n", - "\n", - "# return " + " if not synapse.name in base_global_attrs[\"synapses\"]:\n", + " base_global_attrs[\"synapses\"][synapse.name] = synapse\n", + " updated_base = replace(pre_view.base, global_attrs=base_global_attrs)\n", + " updated_view = replace(pre_view, base=updated_base)\n", + " updated_view = updated_view._init_edge_attrs(synapse_setter)\n", + " return updated_view\n", + " else:\n", + " return pre_view._set_node_attrs(synapse_setter)" + ] + }, + { + "cell_type": "code", + "execution_count": 717, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'index': Array([ 0, 1, 2, ..., 2627, 2628, -1], dtype=int64),\n", + " 'index_post': Array([ 2, 852, 1412, ..., 2629, 2630, -1], dtype=int64),\n", + " 'index_pre': Array([ 1, 1, 1, ..., 2628, 2629, -1], dtype=int64),\n", + " 'synapse': Array([False, False, False, ..., False, False, False], dtype=bool)}" + ] + }, + "execution_count": 717, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def fill_with(x):\n", + " dtype_str = str(x.dtype)\n", + " if \"float\" in dtype_str:\n", + " return jnp.nan\n", + " elif \"bool\" in dtype_str:\n", + " return False\n", + " elif \"int\" in dtype_str:\n", + " return -1\n", + " else:\n", + " raise TypeError(f\"Unsupported dtype for padding: {x.dtype}\")\n", + "\n", + "new_row = {k: jnp.full((1, *v.shape[1:]), fill_with(v)).astype(v.dtype) for k, v in cell.edge_attrs.items()}\n", + "tree_concat(cell.edge_attrs, new_row)" ] }, { "cell_type": "code", - "execution_count": 502, + "execution_count": 620, "metadata": {}, "outputs": [], "source": [ @@ -443,20 +498,20 @@ " def __init__(self, name=None):\n", " self.name = name if name is not None else \"TestChannel\"\n", " self.states = {\"m\": 0.0, \"h\": 0.0}\n", - " # self.params = {\"E\": jnp.array([0.0]), \"g\": jnp.array([[0.0, 0.0], [0.0, 0.0]])}\n", - " self.params = {\"E\": 0.0, \"g\": 0.0}\n", + " self.params = {\"E\": jnp.array([0.0]), \"g\": jnp.array([[0.0, 0.0], [0.0, 0.0]])}\n", + " # self.params = {\"E\": 0.0, \"g\": 0.0}\n", "\n", "class TestSynapse:\n", " def __init__(self, name=None):\n", " self.name = name if name is not None else \"TestSynapse\"\n", " self.states = {\"g\": 0.0}\n", - " # self.params = {\"E\": jnp.array([0.0]), \"g\": jnp.array([0.0])}\n", - " self.params = {\"E\": 0.0, \"g\": 0.0}" + " self.params = {\"E\": jnp.array([0.0]), \"g\": jnp.array([0.0])}\n", + " # self.params = {\"E\": 0.0, \"g\": 0.0}" ] }, { "cell_type": "code", - "execution_count": 503, + "execution_count": 668, "metadata": {}, "outputs": [], "source": [ @@ -465,6 +520,8 @@ "jax_node_attrs[\"index\"] = jax_node_attrs[\"index\"] -1 # TMP FIX FOR INDEXING, otherwise index drift for select\n", "\n", "jax_node_attrs = {(\"morphology\", k) if k != \"index\" else (k,): v for k, v in jax_node_attrs.items()}\n", + "jax_edge_attrs[\"index\"] = jnp.arange(len(jax_edge_attrs[\"index_pre\"]))\n", + "jax_edge_attrs[\"synapse\"] = jnp.full_like(jax_edge_attrs[\"index\"], False, dtype=bool)\n", "\n", "cell = TestModule(jax_node_attrs, jax_edge_attrs, jax_global_attrs)\n", "view = cell.select(nodes=jnp.array([1, 2, 4, 6, 7]))\n", @@ -478,7 +535,7 @@ }, { "cell_type": "code", - "execution_count": 504, + "execution_count": 623, "metadata": {}, "outputs": [ { @@ -527,127 +584,241 @@ " \n", " \n", " \n", + " 0\n", + " [nan]\n", + " True\n", + " [[nan, nan], [nan, nan]]\n", + " NaN\n", + " NaN\n", + " False\n", + " False\n", + " 1\n", + " 8.119\n", + " 0.00\n", + " 0.00\n", + " 0.00\n", + " False\n", + " \n", + " \n", " 1\n", - " 0.0\n", + " [0.0]\n", " True\n", - " 0.0\n", + " [[0.0, 0.0], [0.0, 0.0]]\n", " 0.0\n", " 0.0\n", " True\n", " True\n", " 1\n", - " 20.0\n", + " 20.000\n", " 1.85\n", " -4.03\n", - " 0.0\n", + " 0.00\n", " True\n", " \n", " \n", " 2\n", - " 0.0\n", + " [0.0]\n", " True\n", - " 0.0\n", + " [[0.0, 0.0], [0.0, 0.0]]\n", " 0.0\n", " 0.0\n", " True\n", " True\n", " 1\n", - " 20.0\n", + " 20.000\n", " 1.98\n", " -6.00\n", - " 0.0\n", + " 0.00\n", " True\n", " \n", " \n", + " 3\n", + " [nan]\n", + " True\n", + " [[nan, nan], [nan, nan]]\n", + " NaN\n", + " NaN\n", + " False\n", + " False\n", + " 1\n", + " 5.810\n", + " 1.99\n", + " -7.26\n", + " 0.00\n", + " False\n", + " \n", + " \n", " 4\n", - " 0.0\n", + " [0.0]\n", " True\n", - " 0.0\n", + " [[0.0, 0.0], [0.0, 0.0]]\n", " 0.0\n", " 0.0\n", " True\n", " True\n", " 1\n", - " 20.0\n", + " 20.000\n", " 2.17\n", " -8.49\n", - " 0.0\n", + " 0.00\n", " True\n", " \n", " \n", - " 6\n", - " 0.0\n", - " True\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " True\n", - " True\n", - " 1\n", - " 20.0\n", - " 2.74\n", - " -9.85\n", - " 0.0\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " \n", + " \n", + " 2625\n", + " [nan]\n", " True\n", + " [[nan, nan], [nan, nan]]\n", + " NaN\n", + " NaN\n", + " False\n", + " False\n", + " 3\n", + " 0.550\n", + " 137.48\n", + " 97.80\n", + " 33.36\n", + " False\n", " \n", " \n", - " 7\n", - " 0.0\n", + " 2626\n", + " [nan]\n", " True\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", + " [[nan, nan], [nan, nan]]\n", + " NaN\n", + " NaN\n", + " False\n", + " False\n", + " 3\n", + " 0.550\n", + " 139.56\n", + " 102.04\n", + " 33.36\n", + " False\n", + " \n", + " \n", + " 2627\n", + " [nan]\n", " True\n", + " [[nan, nan], [nan, nan]]\n", + " NaN\n", + " NaN\n", + " False\n", + " False\n", + " 3\n", + " 0.550\n", + " 139.26\n", + " 106.13\n", + " 30.31\n", + " False\n", + " \n", + " \n", + " 2628\n", + " [nan]\n", " True\n", - " 1\n", - " 20.0\n", - " 3.00\n", - " -10.35\n", - " 0.0\n", + " [[nan, nan], [nan, nan]]\n", + " NaN\n", + " NaN\n", + " False\n", + " False\n", + " 3\n", + " 0.550\n", + " 138.86\n", + " 112.19\n", + " 44.47\n", + " False\n", + " \n", + " \n", + " 2629\n", + " [nan]\n", " True\n", + " [[nan, nan], [nan, nan]]\n", + " NaN\n", + " NaN\n", + " False\n", + " False\n", + " 3\n", + " 0.550\n", + " 138.77\n", + " 112.34\n", + " 44.47\n", + " False\n", " \n", " \n", "\n", + "

2630 rows × 13 columns

\n", "" ], "text/plain": [ - " channels externals groups morphology \\\n", - " E TestChannel g h m i test id r x \n", - "1 0.0 True 0.0 0.0 0.0 True True 1 20.0 1.85 \n", - "2 0.0 True 0.0 0.0 0.0 True True 1 20.0 1.98 \n", - "4 0.0 True 0.0 0.0 0.0 True True 1 20.0 2.17 \n", - "6 0.0 True 0.0 0.0 0.0 True True 1 20.0 2.74 \n", - "7 0.0 True 0.0 0.0 0.0 True True 1 20.0 3.00 \n", + " channels externals \\\n", + " E TestChannel g h m i \n", + "0 [nan] True [[nan, nan], [nan, nan]] NaN NaN False \n", + "1 [0.0] True [[0.0, 0.0], [0.0, 0.0]] 0.0 0.0 True \n", + "2 [0.0] True [[0.0, 0.0], [0.0, 0.0]] 0.0 0.0 True \n", + "3 [nan] True [[nan, nan], [nan, nan]] NaN NaN False \n", + "4 [0.0] True [[0.0, 0.0], [0.0, 0.0]] 0.0 0.0 True \n", + "... ... ... ... ... ... ... \n", + "2625 [nan] True [[nan, nan], [nan, nan]] NaN NaN False \n", + "2626 [nan] True [[nan, nan], [nan, nan]] NaN NaN False \n", + "2627 [nan] True [[nan, nan], [nan, nan]] NaN NaN False \n", + "2628 [nan] True [[nan, nan], [nan, nan]] NaN NaN False \n", + "2629 [nan] True [[nan, nan], [nan, nan]] NaN NaN False \n", "\n", - " recordings \n", - " y z i \n", - "1 -4.03 0.0 True \n", - "2 -6.00 0.0 True \n", - "4 -8.49 0.0 True \n", - "6 -9.85 0.0 True \n", - "7 -10.35 0.0 True " + " groups morphology recordings \n", + " test id r x y z i \n", + "0 False 1 8.119 0.00 0.00 0.00 False \n", + "1 True 1 20.000 1.85 -4.03 0.00 True \n", + "2 True 1 20.000 1.98 -6.00 0.00 True \n", + "3 False 1 5.810 1.99 -7.26 0.00 False \n", + "4 True 1 20.000 2.17 -8.49 0.00 True \n", + "... ... ... ... ... ... ... ... \n", + "2625 False 3 0.550 137.48 97.80 33.36 False \n", + "2626 False 3 0.550 139.56 102.04 33.36 False \n", + "2627 False 3 0.550 139.26 106.13 30.31 False \n", + "2628 False 3 0.550 138.86 112.19 44.47 False \n", + "2629 False 3 0.550 138.77 112.34 44.47 False \n", + "\n", + "[2630 rows x 13 columns]" ] }, - "execution_count": 504, + "execution_count": 623, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "view.nodes" + "view.base.nodes" ] }, { "cell_type": "code", - "execution_count": 467, + "execution_count": 722, "metadata": {}, "outputs": [], "source": [ "@jax.jit\n", "def test():\n", - " new_cell = cell.select(nodes=jnp.array([1, 2])).set(\"r\", 20)\n", - "\n", - "test()\n", + " view = cell.select(nodes=jnp.array([1, 2, 4, 6, 7]))\n", + " view = view.set(\"r\", 20)\n", + " view = view.insert(TestChannel())\n", + " view = view.record(\"i\")\n", + " view = view.add_to_group(\"test\")\n", + " # view = view.stimulate(\"i\", jnp.array([0.0, 0.0]))\n", "\n", "# connect(cell.select(nodes=jnp.array([1, 2])), cell.select(nodes=jnp.array([3, 4])), TestSynapse())\n", "\n",